aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-04-26 10:06:31 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-19 14:00:50 -0400
commitddaf557500664b88951f8b1e9b4cb9d368892fd6 (patch)
treeba273e23eced5308cfc7843d4c3464e0616d604b /drivers
parent5f5d2df8ab0b5b6e8514c69b33cc92cac45cda75 (diff)
Staging: rt28[67]0: merge rt28[67]0/sta/*.[ch]
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/rt2870/sta/aironet.c1313
-rw-r--r--drivers/staging/rt2870/sta/assoc.c1740
-rw-r--r--drivers/staging/rt2870/sta/auth.c461
-rw-r--r--drivers/staging/rt2870/sta/auth_rsp.c149
-rw-r--r--drivers/staging/rt2870/sta/connect.c2470
-rw-r--r--drivers/staging/rt2870/sta/rtmp_data.c2429
-rw-r--r--drivers/staging/rt2870/sta/sanity.c419
-rw-r--r--drivers/staging/rt2870/sta/sync.c1605
-rw-r--r--drivers/staging/rt2870/sta/wpa.c2101
9 files changed, 9 insertions, 12678 deletions
diff --git a/drivers/staging/rt2870/sta/aironet.c b/drivers/staging/rt2870/sta/aironet.c
index 4af4a1906181..72b7f2e6bf7f 100644
--- a/drivers/staging/rt2870/sta/aironet.c
+++ b/drivers/staging/rt2870/sta/aironet.c
@@ -1,1312 +1 @@
1/* #include "../../rt2860/sta/aironet.c"
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 aironet.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 Paul Lin 04-06-15 Initial
36*/
37#include "../rt_config.h"
38
39/*
40 ==========================================================================
41 Description:
42 association state machine init, including state transition and timer init
43 Parameters:
44 S - pointer to the association state machine
45 ==========================================================================
46 */
47VOID AironetStateMachineInit(
48 IN PRTMP_ADAPTER pAd,
49 IN STATE_MACHINE *S,
50 OUT STATE_MACHINE_FUNC Trans[])
51{
52 StateMachineInit(S, Trans, MAX_AIRONET_STATE, MAX_AIRONET_MSG, (STATE_MACHINE_FUNC)Drop, AIRONET_IDLE, AIRONET_MACHINE_BASE);
53 StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_MSG, (STATE_MACHINE_FUNC)AironetMsgAction);
54 StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_SCAN_REQ, (STATE_MACHINE_FUNC)AironetRequestAction);
55 StateMachineSetAction(S, AIRONET_SCANNING, MT2_AIRONET_SCAN_DONE, (STATE_MACHINE_FUNC)AironetReportAction);
56}
57
58/*
59 ==========================================================================
60 Description:
61 This is state machine function.
62 When receiving EAPOL packets which is for 802.1x key management.
63 Use both in WPA, and WPAPSK case.
64 In this function, further dispatch to different functions according to the received packet. 3 categories are :
65 1. normal 4-way pairwisekey and 2-way groupkey handshake
66 2. MIC error (Countermeasures attack) report packet from STA.
67 3. Request for pairwise/group key update from STA
68 Return:
69 ==========================================================================
70*/
71VOID AironetMsgAction(
72 IN PRTMP_ADAPTER pAd,
73 IN MLME_QUEUE_ELEM *Elem)
74{
75 USHORT Length;
76 UCHAR Index, i;
77 PUCHAR pData;
78 PAIRONET_RM_REQUEST_FRAME pRMReq;
79 PRM_REQUEST_ACTION pReqElem;
80
81 DBGPRINT(RT_DEBUG_TRACE, ("-----> AironetMsgAction\n"));
82
83 // 0. Get Aironet IAPP header first
84 pRMReq = (PAIRONET_RM_REQUEST_FRAME) &Elem->Msg[LENGTH_802_11];
85 pData = (PUCHAR) &Elem->Msg[LENGTH_802_11];
86
87 // 1. Change endian format form network to little endian
88 Length = be2cpu16(pRMReq->IAPP.Length);
89
90 // 2.0 Sanity check, this should only happen when CCX 2.0 support is enabled
91 if (pAd->StaCfg.CCXEnable != TRUE)
92 return;
93
94 // 2.1 Radio measurement must be on
95 if (pAd->StaCfg.CCXControl.field.RMEnable != 1)
96 return;
97
98 // 2.2. Debug print all bit information
99 DBGPRINT(RT_DEBUG_TRACE, ("IAPP ID & Length %d\n", Length));
100 DBGPRINT(RT_DEBUG_TRACE, ("IAPP Type %x\n", pRMReq->IAPP.Type));
101 DBGPRINT(RT_DEBUG_TRACE, ("IAPP SubType %x\n", pRMReq->IAPP.SubType));
102 DBGPRINT(RT_DEBUG_TRACE, ("IAPP Dialog Token %x\n", pRMReq->IAPP.Token));
103 DBGPRINT(RT_DEBUG_TRACE, ("IAPP Activation Delay %x\n", pRMReq->Delay));
104 DBGPRINT(RT_DEBUG_TRACE, ("IAPP Measurement Offset %x\n", pRMReq->Offset));
105
106 // 3. Check IAPP frame type, it must be 0x32 for Cisco Aironet extension
107 if (pRMReq->IAPP.Type != AIRONET_IAPP_TYPE)
108 {
109 DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP type for Cisco Aironet extension\n"));
110 return;
111 }
112
113 // 4. Check IAPP frame subtype, it must be 0x01 for Cisco Aironet extension request.
114 // Since we are acting as client only, we will disregards reply subtype.
115 if (pRMReq->IAPP.SubType != AIRONET_IAPP_SUBTYPE_REQUEST)
116 {
117 DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP subtype for Cisco Aironet extension\n"));
118 return;
119 }
120
121 // 5. Verify Destination MAC and Source MAC, both should be all zeros.
122 if (! MAC_ADDR_EQUAL(pRMReq->IAPP.DA, ZERO_MAC_ADDR))
123 {
124 DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP DA for Cisco Aironet extension, it's not Zero\n"));
125 return;
126 }
127
128 if (! MAC_ADDR_EQUAL(pRMReq->IAPP.SA, ZERO_MAC_ADDR))
129 {
130 DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP SA for Cisco Aironet extension, it's not Zero\n"));
131 return;
132 }
133
134 // 6. Reinit all report related fields
135 NdisZeroMemory(pAd->StaCfg.FrameReportBuf, 2048);
136 NdisZeroMemory(pAd->StaCfg.BssReportOffset, sizeof(USHORT) * MAX_LEN_OF_BSS_TABLE);
137 NdisZeroMemory(pAd->StaCfg.MeasurementRequest, sizeof(RM_REQUEST_ACTION) * 4);
138
139 // 7. Point to the start of first element report element
140 pAd->StaCfg.FrameReportLen = LENGTH_802_11 + sizeof(AIRONET_IAPP_HEADER);
141 DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen));
142 pAd->StaCfg.LastBssIndex = 0xff;
143 pAd->StaCfg.RMReqCnt = 0;
144 pAd->StaCfg.ParallelReq = FALSE;
145 pAd->StaCfg.ParallelDuration = 0;
146 pAd->StaCfg.ParallelChannel = 0;
147 pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token;
148 pAd->StaCfg.CurrentRMReqIdx = 0;
149 pAd->StaCfg.CLBusyBytes = 0;
150 // Reset the statistics
151 for (i = 0; i < 8; i++)
152 pAd->StaCfg.RPIDensity[i] = 0;
153
154 Index = 0;
155
156 // 8. Save dialog token for report
157 pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token;
158
159 // Save Activation delay & measurement offset, Not really needed
160
161 // 9. Point to the first request element
162 pData += sizeof(AIRONET_RM_REQUEST_FRAME);
163 // Length should exclude the CISCO Aironet SNAP header
164 Length -= (sizeof(AIRONET_RM_REQUEST_FRAME) - LENGTH_802_1_H);
165
166 // 10. Start Parsing the Measurement elements.
167 // Be careful about multiple MR elements within one frames.
168 while (Length > 0)
169 {
170 pReqElem = (PRM_REQUEST_ACTION) pData;
171 switch (pReqElem->ReqElem.Eid)
172 {
173 case IE_MEASUREMENT_REQUEST:
174 // From the example, it seems we only need to support one request in one frame
175 // There is no multiple request in one frame.
176 // Besides, looks like we need to take care the measurement request only.
177 // The measurement request is always 4 bytes.
178
179 // Start parsing this type of request.
180 // 0. Eid is IE_MEASUREMENT_REQUEST
181 // 1. Length didn't include Eid and Length field, it always be 8.
182 // 2. Measurement Token, we nned to save it for the corresponding report.
183 // 3. Measurement Mode, Although there are definitions, but we din't see value other than
184 // 0 from test specs examples.
185 // 4. Measurement Type, this is what we need to do.
186 switch (pReqElem->ReqElem.Type)
187 {
188 case MSRN_TYPE_CHANNEL_LOAD_REQ:
189 case MSRN_TYPE_NOISE_HIST_REQ:
190 case MSRN_TYPE_BEACON_REQ:
191 // Check the Enable non-serving channel measurement control
192 if (pAd->StaCfg.CCXControl.field.DCRMEnable == 0)
193 {
194 // Check channel before enqueue the action
195 if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel)
196 break;
197 }
198 else
199 {
200 // If off channel measurement, check the TU duration limit
201 if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel)
202 if (pReqElem->Measurement.Duration > pAd->StaCfg.CCXControl.field.TuLimit)
203 break;
204 }
205
206 // Save requests and execute actions later
207 NdisMoveMemory(&pAd->StaCfg.MeasurementRequest[Index], pReqElem, sizeof(RM_REQUEST_ACTION));
208 Index += 1;
209 break;
210
211 case MSRN_TYPE_FRAME_REQ:
212 // Since it's option, we will support later
213 // FrameRequestAction(pAd, pData);
214 break;
215
216 default:
217 break;
218 }
219
220 // Point to next Measurement request
221 pData += sizeof(RM_REQUEST_ACTION);
222 Length -= sizeof(RM_REQUEST_ACTION);
223 break;
224
225 // We accept request only, all others are dropped
226 case IE_MEASUREMENT_REPORT:
227 case IE_AP_TX_POWER:
228 case IE_MEASUREMENT_CAPABILITY:
229 default:
230 return;
231 }
232 }
233
234 // 11. Update some flags and index
235 pAd->StaCfg.RMReqCnt = Index;
236
237 if (Index)
238 {
239 MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL);
240 RT28XX_MLME_HANDLER(pAd);
241 }
242
243 DBGPRINT(RT_DEBUG_TRACE, ("<----- AironetMsgAction\n"));
244}
245
246/*
247 ========================================================================
248
249 Routine Description:
250
251 Arguments:
252
253 Return Value:
254 None
255
256 Note:
257
258 ========================================================================
259*/
260VOID AironetRequestAction(
261 IN PRTMP_ADAPTER pAd,
262 IN MLME_QUEUE_ELEM *Elem)
263{
264 PRM_REQUEST_ACTION pReq;
265
266 // 1. Point to next request element
267 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
268
269 // 2. Parse measurement type and call appropriate functions
270 if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
271 // Channel Load measurement request
272 ChannelLoadRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
273 else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
274 // Noise Histogram measurement request
275 NoiseHistRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
276 else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ)
277 // Beacon measurement request
278 BeaconRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
279 else
280 // Unknown. Do nothing and return, this should never happen
281 return;
282
283 // 3. Peek into the next request, if it's parallel, we will update the scan time to the largest one
284 if ((pAd->StaCfg.CurrentRMReqIdx + 1) < pAd->StaCfg.RMReqCnt)
285 {
286 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx + 1];
287 // Check for parallel bit
288 if ((pReq->ReqElem.Mode & 0x01) && (pReq->Measurement.Channel == pAd->StaCfg.CCXScanChannel))
289 {
290 // Update parallel mode request information
291 pAd->StaCfg.ParallelReq = TRUE;
292 pAd->StaCfg.CCXScanTime = ((pReq->Measurement.Duration > pAd->StaCfg.CCXScanTime) ?
293 (pReq->Measurement.Duration) : (pAd->StaCfg.CCXScanTime));
294 }
295 }
296
297 // 4. Call RT28XX_MLME_HANDLER to execute the request mlme commands, Scan request is the only one used
298 RT28XX_MLME_HANDLER(pAd);
299
300}
301
302
303/*
304 ========================================================================
305
306 Routine Description:
307 Prepare channel load report action, special scan operation added
308 to support
309
310 Arguments:
311 pAd Pointer to our adapter
312 pData Start from element ID
313
314 Return Value:
315 None
316
317 Note:
318
319 ========================================================================
320*/
321VOID ChannelLoadRequestAction(
322 IN PRTMP_ADAPTER pAd,
323 IN UCHAR Index)
324{
325 PRM_REQUEST_ACTION pReq;
326 MLME_SCAN_REQ_STRUCT ScanReq;
327 UCHAR ZeroSsid[32];
328 NDIS_STATUS NStatus;
329 PUCHAR pOutBuffer = NULL;
330 PHEADER_802_11 pNullFrame;
331
332 DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction ----->\n"));
333
334 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
335 NdisZeroMemory(ZeroSsid, 32);
336
337 // Prepare for special scan request
338 // The scan definition is different with our Active, Passive scan definition.
339 // For CCX2, Active means send out probe request with broadcast BSSID.
340 // Passive means no probe request sent, only listen to the beacons.
341 // The channel scanned is fixed as specified, no need to scan all channels.
342 // The scan wait time is specified in the request too.
343 // Passive scan Mode
344
345 // Control state machine is not idle, reject the request
346 if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
347 return;
348
349 // Fill out stuff for scan request
350 ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_CHANNEL_LOAD);
351 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
352 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
353
354 // Reset some internal control flags to make sure this scan works.
355 BssTableInit(&pAd->StaCfg.CCXBssTab);
356 pAd->StaCfg.ScanCnt = 0;
357 pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
358 pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration;
359
360 DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel));
361
362 // If it's non serving channel scan, send out a null frame with PSM bit on.
363 if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
364 {
365 // Use MLME enqueue method
366 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
367 if (NStatus != NDIS_STATUS_SUCCESS)
368 return;
369
370 pNullFrame = (PHEADER_802_11) pOutBuffer;;
371 // Make the power save Null frame with PSM bit on
372 MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
373 pNullFrame->Duration = 0;
374 pNullFrame->FC.Type = BTYPE_DATA;
375 pNullFrame->FC.PwrMgmt = PWR_SAVE;
376
377 // Send using priority queue
378 MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
379 MlmeFreeMemory(pAd, pOutBuffer);
380 DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
381 RTMPusecDelay(5000);
382 }
383
384 pAd->StaCfg.CCXReqType = MSRN_TYPE_CHANNEL_LOAD_REQ;
385 pAd->StaCfg.CLBusyBytes = 0;
386 // Enable Rx with promiscuous reception
387 RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010);
388
389 // Set channel load measurement flag
390 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
391
392 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
393
394 DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction <-----\n"));
395}
396
397/*
398 ========================================================================
399
400 Routine Description:
401 Prepare noise histogram report action, special scan operation added
402 to support
403
404 Arguments:
405 pAd Pointer to our adapter
406 pData Start from element ID
407
408 Return Value:
409 None
410
411 Note:
412
413 ========================================================================
414*/
415VOID NoiseHistRequestAction(
416 IN PRTMP_ADAPTER pAd,
417 IN UCHAR Index)
418{
419 PRM_REQUEST_ACTION pReq;
420 MLME_SCAN_REQ_STRUCT ScanReq;
421 UCHAR ZeroSsid[32], i;
422 NDIS_STATUS NStatus;
423 PUCHAR pOutBuffer = NULL;
424 PHEADER_802_11 pNullFrame;
425
426 DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction ----->\n"));
427
428 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
429 NdisZeroMemory(ZeroSsid, 32);
430
431 // Prepare for special scan request
432 // The scan definition is different with our Active, Passive scan definition.
433 // For CCX2, Active means send out probe request with broadcast BSSID.
434 // Passive means no probe request sent, only listen to the beacons.
435 // The channel scanned is fixed as specified, no need to scan all channels.
436 // The scan wait time is specified in the request too.
437 // Passive scan Mode
438
439 // Control state machine is not idle, reject the request
440 if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
441 return;
442
443 // Fill out stuff for scan request
444 ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_NOISE);
445 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
446 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
447
448 // Reset some internal control flags to make sure this scan works.
449 BssTableInit(&pAd->StaCfg.CCXBssTab);
450 pAd->StaCfg.ScanCnt = 0;
451 pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
452 pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration;
453 pAd->StaCfg.CCXReqType = MSRN_TYPE_NOISE_HIST_REQ;
454
455 DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel));
456
457 // If it's non serving channel scan, send out a null frame with PSM bit on.
458 if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
459 {
460 // Use MLME enqueue method
461 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
462 if (NStatus != NDIS_STATUS_SUCCESS)
463 return;
464
465 pNullFrame = (PHEADER_802_11) pOutBuffer;
466 // Make the power save Null frame with PSM bit on
467 MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
468 pNullFrame->Duration = 0;
469 pNullFrame->FC.Type = BTYPE_DATA;
470 pNullFrame->FC.PwrMgmt = PWR_SAVE;
471
472 // Send using priority queue
473 MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
474 MlmeFreeMemory(pAd, pOutBuffer);
475 DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
476 RTMPusecDelay(5000);
477 }
478
479 // Reset the statistics
480 for (i = 0; i < 8; i++)
481 pAd->StaCfg.RPIDensity[i] = 0;
482
483 // Enable Rx with promiscuous reception
484 RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010);
485
486 // Set channel load measurement flag
487 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
488
489 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
490
491 DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction <-----\n"));
492}
493
494/*
495 ========================================================================
496
497 Routine Description:
498 Prepare Beacon report action, special scan operation added
499 to support
500
501 Arguments:
502 pAd Pointer to our adapter
503 pData Start from element ID
504
505 Return Value:
506 None
507
508 Note:
509
510 ========================================================================
511*/
512VOID BeaconRequestAction(
513 IN PRTMP_ADAPTER pAd,
514 IN UCHAR Index)
515{
516 PRM_REQUEST_ACTION pReq;
517 NDIS_STATUS NStatus;
518 PUCHAR pOutBuffer = NULL;
519 PHEADER_802_11 pNullFrame;
520 MLME_SCAN_REQ_STRUCT ScanReq;
521 UCHAR ZeroSsid[32];
522
523 DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction ----->\n"));
524
525 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
526 NdisZeroMemory(ZeroSsid, 32);
527
528 // Prepare for special scan request
529 // The scan definition is different with our Active, Passive scan definition.
530 // For CCX2, Active means send out probe request with broadcast BSSID.
531 // Passive means no probe request sent, only listen to the beacons.
532 // The channel scanned is fixed as specified, no need to scan all channels.
533 // The scan wait time is specified in the request too.
534 if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_PASSIVE)
535 {
536 // Passive scan Mode
537 DBGPRINT(RT_DEBUG_TRACE, ("Passive Scan Mode!\n"));
538
539 // Control state machine is not idle, reject the request
540 if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
541 return;
542
543 // Fill out stuff for scan request
544 ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_PASSIVE);
545 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
546 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
547
548 // Reset some internal control flags to make sure this scan works.
549 BssTableInit(&pAd->StaCfg.CCXBssTab);
550 pAd->StaCfg.ScanCnt = 0;
551 pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
552 pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration;
553 pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ;
554 DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration));
555
556 // If it's non serving channel scan, send out a null frame with PSM bit on.
557 if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
558 {
559 // Use MLME enqueue method
560 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
561 if (NStatus != NDIS_STATUS_SUCCESS)
562 return;
563
564 pNullFrame = (PHEADER_802_11) pOutBuffer;
565 // Make the power save Null frame with PSM bit on
566 MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
567 pNullFrame->Duration = 0;
568 pNullFrame->FC.Type = BTYPE_DATA;
569 pNullFrame->FC.PwrMgmt = PWR_SAVE;
570
571 // Send using priority queue
572 MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
573 MlmeFreeMemory(pAd, pOutBuffer);
574 DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
575 RTMPusecDelay(5000);
576 }
577
578 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
579 }
580 else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_ACTIVE)
581 {
582 // Active scan Mode
583 DBGPRINT(RT_DEBUG_TRACE, ("Active Scan Mode!\n"));
584
585 // Control state machine is not idle, reject the request
586 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
587 return;
588
589 // Fill out stuff for scan request
590 ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_ACTIVE);
591 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
592 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
593
594 // Reset some internal control flags to make sure this scan works.
595 BssTableInit(&pAd->StaCfg.CCXBssTab);
596 pAd->StaCfg.ScanCnt = 0;
597 pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
598 pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration;
599 pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ;
600 DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration));
601
602 // If it's non serving channel scan, send out a null frame with PSM bit on.
603 if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
604 {
605 // Use MLME enqueue method
606 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
607 if (NStatus != NDIS_STATUS_SUCCESS)
608 return;
609
610 pNullFrame = (PHEADER_802_11) pOutBuffer;
611 // Make the power save Null frame with PSM bit on
612 MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
613 pNullFrame->Duration = 0;
614 pNullFrame->FC.Type = BTYPE_DATA;
615 pNullFrame->FC.PwrMgmt = PWR_SAVE;
616
617 // Send using priority queue
618 MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
619 MlmeFreeMemory(pAd, pOutBuffer);
620 DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
621 RTMPusecDelay(5000);
622 }
623
624 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
625 }
626 else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_BEACON_TABLE)
627 {
628 // Beacon report Mode, report all the APS in current bss table
629 DBGPRINT(RT_DEBUG_TRACE, ("Beacon Report Mode!\n"));
630
631 // Copy current BSS table to CCX table, we can omit this step later on.
632 NdisMoveMemory(&pAd->StaCfg.CCXBssTab, &pAd->ScanTab, sizeof(BSS_TABLE));
633
634 // Create beacon report from Bss table
635 AironetCreateBeaconReportFromBssTable(pAd);
636
637 // Set state to scanning
638 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
639
640 // Enqueue report request
641 // Cisco scan request is finished, prepare beacon report
642 MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL);
643 }
644 else
645 {
646 // Wrong scan Mode
647 DBGPRINT(RT_DEBUG_TRACE, ("Wrong Scan Mode!\n"));
648 }
649
650 DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction <-----\n"));
651}
652
653/*
654 ========================================================================
655
656 Routine Description:
657
658 Arguments:
659
660 Return Value:
661 None
662
663 Note:
664
665 ========================================================================
666*/
667VOID AironetReportAction(
668 IN PRTMP_ADAPTER pAd,
669 IN MLME_QUEUE_ELEM *Elem)
670{
671 PRM_REQUEST_ACTION pReq;
672 ULONG Now32;
673
674 NdisGetSystemUpTime(&Now32);
675 pAd->StaCfg.LastBeaconRxTime = Now32;
676
677 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
678
679 DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction ----->\n"));
680
681 // 1. Parse measurement type and call appropriate functions
682 if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
683 // Channel Load measurement request
684 ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
685 else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
686 // Noise Histogram measurement request
687 NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
688 else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ)
689 // Beacon measurement request
690 BeaconReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
691 else
692 // Unknown. Do nothing and return
693 ;
694
695 // 2. Point to the correct index of action element, start from 0
696 pAd->StaCfg.CurrentRMReqIdx++;
697
698 // 3. Check for parallel actions
699 if (pAd->StaCfg.ParallelReq == TRUE)
700 {
701 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
702
703 // Process next action right away
704 if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
705 // Channel Load measurement request
706 ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
707 else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
708 // Noise Histogram measurement request
709 NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
710
711 pAd->StaCfg.ParallelReq = FALSE;
712 pAd->StaCfg.CurrentRMReqIdx++;
713 }
714
715 if (pAd->StaCfg.CurrentRMReqIdx >= pAd->StaCfg.RMReqCnt)
716 {
717 // 4. There is no more unprocessed measurement request, go for transmit this report
718 AironetFinalReportAction(pAd);
719 pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
720 }
721 else
722 {
723 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
724
725 if (pReq->Measurement.Channel != pAd->CommonCfg.Channel)
726 {
727 RTMPusecDelay(100000);
728 }
729
730 // 5. There are more requests to be measure
731 MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL);
732 RT28XX_MLME_HANDLER(pAd);
733 }
734
735 DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction <-----\n"));
736}
737
738/*
739 ========================================================================
740
741 Routine Description:
742
743 Arguments:
744
745 Return Value:
746 None
747
748 Note:
749
750 ========================================================================
751*/
752VOID AironetFinalReportAction(
753 IN PRTMP_ADAPTER pAd)
754{
755 PUCHAR pDest;
756 PAIRONET_IAPP_HEADER pIAPP;
757 PHEADER_802_11 pHeader;
758 UCHAR AckRate = RATE_2;
759 USHORT AckDuration = 0;
760 NDIS_STATUS NStatus;
761 PUCHAR pOutBuffer = NULL;
762 ULONG FrameLen = 0;
763
764 DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction ----->\n"));
765
766 // 0. Set up the frame pointer, Frame was inited at the end of message action
767 pDest = &pAd->StaCfg.FrameReportBuf[LENGTH_802_11];
768
769 // 1. Update report IAPP fields
770 pIAPP = (PAIRONET_IAPP_HEADER) pDest;
771
772 // 2. Copy Cisco SNAP header
773 NdisMoveMemory(pIAPP->CiscoSnapHeader, SNAP_AIRONET, LENGTH_802_1_H);
774
775 // 3. network order for this 16bit length
776 pIAPP->Length = cpu2be16(pAd->StaCfg.FrameReportLen - LENGTH_802_11 - LENGTH_802_1_H);
777
778 // 3.1 sanity check the report length, ignore it if there is nothing to report
779 if (be2cpu16(pIAPP->Length) <= 18)
780 return;
781
782 // 4. Type must be 0x32
783 pIAPP->Type = AIRONET_IAPP_TYPE;
784
785 // 5. SubType for report must be 0x81
786 pIAPP->SubType = AIRONET_IAPP_SUBTYPE_REPORT;
787
788 // 6. DA is not used and must be zero, although the whole frame was cleared at the start of function
789 // We will do it again here. We can use BSSID instead
790 COPY_MAC_ADDR(pIAPP->DA, pAd->CommonCfg.Bssid);
791
792 // 7. SA is the client reporting which must be our MAC
793 COPY_MAC_ADDR(pIAPP->SA, pAd->CurrentAddress);
794
795 // 8. Copy the saved dialog token
796 pIAPP->Token = pAd->StaCfg.IAPPToken;
797
798 // 9. Make the Report frame 802.11 header
799 // Reuse function in wpa.c
800 pHeader = (PHEADER_802_11) pAd->StaCfg.FrameReportBuf;
801 pAd->Sequence ++;
802 WpaMacHeaderInit(pAd, pHeader, 0, pAd->CommonCfg.Bssid);
803
804 // ACK size is 14 include CRC, and its rate is based on real time information
805 AckRate = pAd->CommonCfg.ExpectedACKRate[pAd->CommonCfg.MlmeRate];
806 AckDuration = RTMPCalcDuration(pAd, AckRate, 14);
807 pHeader->Duration = pAd->CommonCfg.Dsifs + AckDuration;
808
809 // Use MLME enqueue method
810 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
811 if (NStatus != NDIS_STATUS_SUCCESS)
812 return;
813
814 // 10. Prepare report frame with dynamic outbuffer. Just simply copy everything.
815 MakeOutgoingFrame(pOutBuffer, &FrameLen,
816 pAd->StaCfg.FrameReportLen, pAd->StaCfg.FrameReportBuf,
817 END_OF_ARGS);
818
819 // 11. Send using priority queue
820 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
821 MlmeFreeMemory(pAd, pOutBuffer);
822
823 pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED;
824
825 DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction <-----\n"));
826}
827
828/*
829 ========================================================================
830
831 Routine Description:
832
833 Arguments:
834
835 Return Value:
836 None
837
838 Note:
839
840 ========================================================================
841*/
842VOID ChannelLoadReportAction(
843 IN PRTMP_ADAPTER pAd,
844 IN UCHAR Index)
845{
846 PMEASUREMENT_REPORT_ELEMENT pReport;
847 PCHANNEL_LOAD_REPORT pLoad;
848 PUCHAR pDest;
849 UCHAR CCABusyFraction;
850
851 DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction ----->\n"));
852
853 // Disable Rx with promiscuous reception, make it back to normal
854 RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification.
855
856 // 0. Setup pointer for processing beacon & probe response
857 pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
858 pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
859
860 // 1. Fill Measurement report element field.
861 pReport->Eid = IE_MEASUREMENT_REPORT;
862 // Fixed Length at 9, not include Eid and length fields
863 pReport->Length = 9;
864 pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token;
865 pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode;
866 pReport->Type = MSRN_TYPE_CHANNEL_LOAD_REQ;
867
868 // 2. Fill channel report measurement data
869 pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
870 pLoad = (PCHANNEL_LOAD_REPORT) pDest;
871 pLoad->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel;
872 pLoad->Spare = 0;
873 pLoad->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration;
874
875 // 3. Calculate the CCA Busy Fraction
876 // (Bytes + ACK size) * 8 / Tx speed * 255 / 1000 / measurement duration, use 24 us Tx speed
877 // = (Bytes + ACK) / 12 / duration
878 // 9 is the good value for pAd->StaCfg.CLFactor
879 // CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 9 / pLoad->Duration);
880 CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / pAd->StaCfg.CLFactor / pLoad->Duration);
881 if (CCABusyFraction < 10)
882 CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 3 / pLoad->Duration) + 1;
883
884 pLoad->CCABusy = CCABusyFraction;
885 DBGPRINT(RT_DEBUG_TRACE, ("CLBusyByte %ld, Duration %d, Result, %d\n", pAd->StaCfg.CLBusyBytes, pLoad->Duration, CCABusyFraction));
886
887 DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen));
888 pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(CHANNEL_LOAD_REPORT));
889 DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen));
890
891 // 4. Clear channel load measurement flag
892 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
893
894 // 5. reset to idle state
895 pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
896
897 DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction <-----\n"));
898}
899
900/*
901 ========================================================================
902
903 Routine Description:
904
905 Arguments:
906
907 Return Value:
908 None
909
910 Note:
911
912 ========================================================================
913*/
914VOID NoiseHistReportAction(
915 IN PRTMP_ADAPTER pAd,
916 IN UCHAR Index)
917{
918 PMEASUREMENT_REPORT_ELEMENT pReport;
919 PNOISE_HIST_REPORT pNoise;
920 PUCHAR pDest;
921 UCHAR i,NoiseCnt;
922 USHORT TotalRPICnt, TotalRPISum;
923
924 DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction ----->\n"));
925
926 // 0. Disable Rx with promiscuous reception, make it back to normal
927 RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification.
928 // 1. Setup pointer for processing beacon & probe response
929 pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
930 pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
931
932 // 2. Fill Measurement report element field.
933 pReport->Eid = IE_MEASUREMENT_REPORT;
934 // Fixed Length at 16, not include Eid and length fields
935 pReport->Length = 16;
936 pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token;
937 pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode;
938 pReport->Type = MSRN_TYPE_NOISE_HIST_REQ;
939
940 // 3. Fill noise histogram report measurement data
941 pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
942 pNoise = (PNOISE_HIST_REPORT) pDest;
943 pNoise->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel;
944 pNoise->Spare = 0;
945 pNoise->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration;
946 // 4. Fill Noise histogram, the total RPI counts should be 0.4 * TU
947 // We estimate 4000 normal packets received durning 10 seconds test.
948 // Adjust it if required.
949 // 3 is a good value for pAd->StaCfg.NHFactor
950 // TotalRPICnt = pNoise->Duration * 3 / 10;
951 TotalRPICnt = pNoise->Duration * pAd->StaCfg.NHFactor / 10;
952 TotalRPISum = 0;
953
954 for (i = 0; i < 8; i++)
955 {
956 TotalRPISum += pAd->StaCfg.RPIDensity[i];
957 DBGPRINT(RT_DEBUG_TRACE, ("RPI %d Conuts %d\n", i, pAd->StaCfg.RPIDensity[i]));
958 }
959
960 // Double check if the counter is larger than our expectation.
961 // We will replace it with the total number plus a fraction.
962 if (TotalRPISum > TotalRPICnt)
963 TotalRPICnt = TotalRPISum + pNoise->Duration / 20;
964
965 DBGPRINT(RT_DEBUG_TRACE, ("Total RPI Conuts %d\n", TotalRPICnt));
966
967 // 5. Initialize noise count for the total summation of 0xff
968 NoiseCnt = 0;
969 for (i = 1; i < 8; i++)
970 {
971 pNoise->Density[i] = (UCHAR) (pAd->StaCfg.RPIDensity[i] * 255 / TotalRPICnt);
972 if ((pNoise->Density[i] == 0) && (pAd->StaCfg.RPIDensity[i] != 0))
973 pNoise->Density[i]++;
974 NoiseCnt += pNoise->Density[i];
975 DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[%d] = 0x%02x\n", i, pNoise->Density[i]));
976 }
977
978 // 6. RPI[0] represents the rest of counts
979 pNoise->Density[0] = 0xff - NoiseCnt;
980 DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[0] = 0x%02x\n", pNoise->Density[0]));
981
982 pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(NOISE_HIST_REPORT));
983
984 // 7. Clear channel load measurement flag
985 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
986
987 // 8. reset to idle state
988 pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
989
990 DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction <-----\n"));
991}
992
993/*
994 ========================================================================
995
996 Routine Description:
997 Prepare Beacon report action,
998
999 Arguments:
1000 pAd Pointer to our adapter
1001
1002 Return Value:
1003 None
1004
1005 Note:
1006
1007 ========================================================================
1008*/
1009VOID BeaconReportAction(
1010 IN PRTMP_ADAPTER pAd,
1011 IN UCHAR Index)
1012{
1013 DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction ----->\n"));
1014
1015 // Looks like we don't have anything thing need to do here.
1016 // All measurement report already finished in AddBeaconReport
1017 // The length is in the FrameReportLen
1018
1019 // reset Beacon index for next beacon request
1020 pAd->StaCfg.LastBssIndex = 0xff;
1021
1022 // reset to idle state
1023 pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
1024
1025 DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction <-----\n"));
1026}
1027
1028/*
1029 ========================================================================
1030
1031 Routine Description:
1032
1033 Arguments:
1034 Index Current BSSID in CCXBsstab entry index
1035
1036 Return Value:
1037
1038 Note:
1039
1040 ========================================================================
1041*/
1042VOID AironetAddBeaconReport(
1043 IN PRTMP_ADAPTER pAd,
1044 IN ULONG Index,
1045 IN PMLME_QUEUE_ELEM pElem)
1046{
1047 PVOID pMsg;
1048 PUCHAR pSrc, pDest;
1049 UCHAR ReqIdx;
1050 ULONG MsgLen;
1051 USHORT Length;
1052 PFRAME_802_11 pFrame;
1053 PMEASUREMENT_REPORT_ELEMENT pReport;
1054 PEID_STRUCT pEid;
1055 PBEACON_REPORT pBeaconReport;
1056 PBSS_ENTRY pBss;
1057
1058 // 0. Setup pointer for processing beacon & probe response
1059 pMsg = pElem->Msg;
1060 MsgLen = pElem->MsgLen;
1061 pFrame = (PFRAME_802_11) pMsg;
1062 pSrc = pFrame->Octet; // Start from AP TSF
1063 pBss = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index];
1064 ReqIdx = pAd->StaCfg.CurrentRMReqIdx;
1065
1066 // 1 Check the Index, if we already create this entry, only update the average RSSI
1067 if ((Index <= pAd->StaCfg.LastBssIndex) && (pAd->StaCfg.LastBssIndex != 0xff))
1068 {
1069 pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.BssReportOffset[Index]];
1070 // Point to bss report information
1071 pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
1072 pBeaconReport = (PBEACON_REPORT) pDest;
1073
1074 // Update Rx power, in dBm
1075 // Get the original RSSI readback from BBP
1076 pBeaconReport->RxPower += pAd->BbpRssiToDbmDelta;
1077 // Average the Rssi reading
1078 pBeaconReport->RxPower = (pBeaconReport->RxPower + pBss->Rssi) / 2;
1079 // Get to dBm format
1080 pBeaconReport->RxPower -= pAd->BbpRssiToDbmDelta;
1081
1082 DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ",
1083 pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2],
1084 pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
1085 DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld] Rssi %d, Avg Rssi %d\n", Index, (pBss->Rssi - pAd->BbpRssiToDbmDelta), pBeaconReport->RxPower - 256));
1086 DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.BssReportOffset[Index]));
1087
1088 // Update other information here
1089
1090 // Done
1091 return;
1092 }
1093
1094 // 2. Update reported Index
1095 pAd->StaCfg.LastBssIndex = Index;
1096
1097 // 3. Setup the buffer address for copying this BSSID into reporting frame
1098 // The offset should start after 802.11 header and report frame header.
1099 pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
1100
1101 // 4. Save the start offset of each Bss in report frame
1102 pAd->StaCfg.BssReportOffset[Index] = pAd->StaCfg.FrameReportLen;
1103
1104 // 5. Fill Measurement report fields
1105 pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
1106 pReport->Eid = IE_MEASUREMENT_REPORT;
1107 pReport->Length = 0;
1108 pReport->Token = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token;
1109 pReport->Mode = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode;
1110 pReport->Type = MSRN_TYPE_BEACON_REQ;
1111 Length = sizeof(MEASUREMENT_REPORT_ELEMENT);
1112 pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
1113
1114 // 6. Start thebeacon report format
1115 pBeaconReport = (PBEACON_REPORT) pDest;
1116 pDest += sizeof(BEACON_REPORT);
1117 Length += sizeof(BEACON_REPORT);
1118
1119 // 7. Copy Channel number
1120 pBeaconReport->Channel = pBss->Channel;
1121 pBeaconReport->Spare = 0;
1122 pBeaconReport->Duration = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration;
1123 pBeaconReport->PhyType = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS);
1124 // 8. Rx power, in dBm
1125 pBeaconReport->RxPower = pBss->Rssi - pAd->BbpRssiToDbmDelta;
1126
1127 DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ",
1128 pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2],
1129 pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
1130 DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld], Rssi %d\n", Index, pBeaconReport->RxPower - 256));
1131 DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.FrameReportLen));
1132
1133 pBeaconReport->BeaconInterval = pBss->BeaconPeriod;
1134 COPY_MAC_ADDR(pBeaconReport->BSSID, pFrame->Hdr.Addr3);
1135 NdisMoveMemory(pBeaconReport->ParentTSF, pSrc, 4);
1136 NdisMoveMemory(pBeaconReport->TargetTSF, &pElem->TimeStamp.u.LowPart, 4);
1137 NdisMoveMemory(&pBeaconReport->TargetTSF[4], &pElem->TimeStamp.u.HighPart, 4);
1138
1139 // 9. Skip the beacon frame and offset to start of capabilityinfo since we already processed capabilityinfo
1140 pSrc += (TIMESTAMP_LEN + 2);
1141 pBeaconReport->CapabilityInfo = *(USHORT *)pSrc;
1142
1143 // 10. Point to start of element ID
1144 pSrc += 2;
1145 pEid = (PEID_STRUCT) pSrc;
1146
1147 // 11. Start process all variable Eid oayload and add the appropriate to the frame report
1148 while (((PUCHAR) pEid + pEid->Len + 1) < ((PUCHAR) pFrame + MsgLen))
1149 {
1150 // Only limited EID are required to report for CCX 2. It includes SSID, Supported rate,
1151 // FH paramenter set, DS parameter set, CF parameter set, IBSS parameter set,
1152 // TIM (report first 4 bytes only, radio measurement capability
1153 switch (pEid->Eid)
1154 {
1155 case IE_SSID:
1156 case IE_SUPP_RATES:
1157 case IE_FH_PARM:
1158 case IE_DS_PARM:
1159 case IE_CF_PARM:
1160 case IE_IBSS_PARM:
1161 NdisMoveMemory(pDest, pEid, pEid->Len + 2);
1162 pDest += (pEid->Len + 2);
1163 Length += (pEid->Len + 2);
1164 break;
1165
1166 case IE_MEASUREMENT_CAPABILITY:
1167 // Since this IE is duplicated with WPA security IE, we has to do sanity check before
1168 // recognize it.
1169 // 1. It also has fixed 6 bytes IE length.
1170 if (pEid->Len != 6)
1171 break;
1172 // 2. Check the Cisco Aironet OUI
1173 if (NdisEqualMemory(CISCO_OUI, (pSrc + 2), 3))
1174 {
1175 // Matched, this is what we want
1176 NdisMoveMemory(pDest, pEid, pEid->Len + 2);
1177 pDest += (pEid->Len + 2);
1178 Length += (pEid->Len + 2);
1179 }
1180 break;
1181
1182 case IE_TIM:
1183 if (pEid->Len > 4)
1184 {
1185 // May truncate and report the first 4 bytes only, with the eid & len, total should be 6
1186 NdisMoveMemory(pDest, pEid, 6);
1187 pDest += 6;
1188 Length += 6;
1189 }
1190 else
1191 {
1192 NdisMoveMemory(pDest, pEid, pEid->Len + 2);
1193 pDest += (pEid->Len + 2);
1194 Length += (pEid->Len + 2);
1195 }
1196 break;
1197
1198 default:
1199 break;
1200 }
1201 // 12. Move to next element ID
1202 pSrc += (2 + pEid->Len);
1203 pEid = (PEID_STRUCT) pSrc;
1204 }
1205
1206 // 13. Update the length in the header, not include EID and length
1207 pReport->Length = Length - 4;
1208
1209 // 14. Update the frame report buffer data length
1210 pAd->StaCfg.FrameReportLen += Length;
1211 DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen));
1212}
1213
1214/*
1215 ========================================================================
1216
1217 Routine Description:
1218
1219 Arguments:
1220 Index Current BSSID in CCXBsstab entry index
1221
1222 Return Value:
1223
1224 Note:
1225
1226 ========================================================================
1227*/
1228VOID AironetCreateBeaconReportFromBssTable(
1229 IN PRTMP_ADAPTER pAd)
1230{
1231 PMEASUREMENT_REPORT_ELEMENT pReport;
1232 PBEACON_REPORT pBeaconReport;
1233 UCHAR Index, ReqIdx;
1234 USHORT Length;
1235 PUCHAR pDest;
1236 PBSS_ENTRY pBss;
1237
1238 // 0. setup base pointer
1239 ReqIdx = pAd->StaCfg.CurrentRMReqIdx;
1240
1241 for (Index = 0; Index < pAd->StaCfg.CCXBssTab.BssNr; Index++)
1242 {
1243 // 1. Setup the buffer address for copying this BSSID into reporting frame
1244 // The offset should start after 802.11 header and report frame header.
1245 pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
1246 pBss = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index];
1247 Length = 0;
1248
1249 // 2. Fill Measurement report fields
1250 pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
1251 pReport->Eid = IE_MEASUREMENT_REPORT;
1252 pReport->Length = 0;
1253 pReport->Token = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token;
1254 pReport->Mode = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode;
1255 pReport->Type = MSRN_TYPE_BEACON_REQ;
1256 Length = sizeof(MEASUREMENT_REPORT_ELEMENT);
1257 pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
1258
1259 // 3. Start the beacon report format
1260 pBeaconReport = (PBEACON_REPORT) pDest;
1261 pDest += sizeof(BEACON_REPORT);
1262 Length += sizeof(BEACON_REPORT);
1263
1264 // 4. Copy Channel number
1265 pBeaconReport->Channel = pBss->Channel;
1266 pBeaconReport->Spare = 0;
1267 pBeaconReport->Duration = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration;
1268 pBeaconReport->PhyType = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS);
1269 pBeaconReport->RxPower = pBss->Rssi - pAd->BbpRssiToDbmDelta;
1270 pBeaconReport->BeaconInterval = pBss->BeaconPeriod;
1271 pBeaconReport->CapabilityInfo = pBss->CapabilityInfo;
1272 COPY_MAC_ADDR(pBeaconReport->BSSID, pBss->Bssid);
1273 NdisMoveMemory(pBeaconReport->ParentTSF, pBss->PTSF, 4);
1274 NdisMoveMemory(pBeaconReport->TargetTSF, pBss->TTSF, 8);
1275
1276 // 5. Create SSID
1277 *pDest++ = 0x00;
1278 *pDest++ = pBss->SsidLen;
1279 NdisMoveMemory(pDest, pBss->Ssid, pBss->SsidLen);
1280 pDest += pBss->SsidLen;
1281 Length += (2 + pBss->SsidLen);
1282
1283 // 6. Create SupportRates
1284 *pDest++ = 0x01;
1285 *pDest++ = pBss->SupRateLen;
1286 NdisMoveMemory(pDest, pBss->SupRate, pBss->SupRateLen);
1287 pDest += pBss->SupRateLen;
1288 Length += (2 + pBss->SupRateLen);
1289
1290 // 7. DS Parameter
1291 *pDest++ = 0x03;
1292 *pDest++ = 1;
1293 *pDest++ = pBss->Channel;
1294 Length += 3;
1295
1296 // 8. IBSS parameter if presents
1297 if (pBss->BssType == BSS_ADHOC)
1298 {
1299 *pDest++ = 0x06;
1300 *pDest++ = 2;
1301 *(PUSHORT) pDest = pBss->AtimWin;
1302 pDest += 2;
1303 Length += 4;
1304 }
1305
1306 // 9. Update length field, not include EID and length
1307 pReport->Length = Length - 4;
1308
1309 // 10. Update total frame size
1310 pAd->StaCfg.FrameReportLen += Length;
1311 }
1312}
diff --git a/drivers/staging/rt2870/sta/assoc.c b/drivers/staging/rt2870/sta/assoc.c
index d23dd05f79b8..46564d7a01a9 100644
--- a/drivers/staging/rt2870/sta/assoc.c
+++ b/drivers/staging/rt2870/sta/assoc.c
@@ -1,1739 +1 @@
1/* #include "../../rt2860/sta/assoc.c"
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 assoc.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 John 2004-9-3 porting from RT2500
36*/
37#include "../rt_config.h"
38
39UCHAR CipherWpaTemplate[] = {
40 0xdd, // WPA IE
41 0x16, // Length
42 0x00, 0x50, 0xf2, 0x01, // oui
43 0x01, 0x00, // Version
44 0x00, 0x50, 0xf2, 0x02, // Multicast
45 0x01, 0x00, // Number of unicast
46 0x00, 0x50, 0xf2, 0x02, // unicast
47 0x01, 0x00, // number of authentication method
48 0x00, 0x50, 0xf2, 0x01 // authentication
49 };
50
51UCHAR CipherWpa2Template[] = {
52 0x30, // RSN IE
53 0x14, // Length
54 0x01, 0x00, // Version
55 0x00, 0x0f, 0xac, 0x02, // group cipher, TKIP
56 0x01, 0x00, // number of pairwise
57 0x00, 0x0f, 0xac, 0x02, // unicast
58 0x01, 0x00, // number of authentication method
59 0x00, 0x0f, 0xac, 0x02, // authentication
60 0x00, 0x00, // RSN capability
61 };
62
63UCHAR Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02};
64
65/*
66 ==========================================================================
67 Description:
68 association state machine init, including state transition and timer init
69 Parameters:
70 S - pointer to the association state machine
71
72 IRQL = PASSIVE_LEVEL
73
74 ==========================================================================
75 */
76VOID AssocStateMachineInit(
77 IN PRTMP_ADAPTER pAd,
78 IN STATE_MACHINE *S,
79 OUT STATE_MACHINE_FUNC Trans[])
80{
81 StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, ASSOC_IDLE, ASSOC_MACHINE_BASE);
82
83 // first column
84 StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)MlmeAssocReqAction);
85 StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)MlmeReassocReqAction);
86 StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)MlmeDisassocReqAction);
87 StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
88
89 // second column
90 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
91 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
92 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
93 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
94 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction);
95 //
96 // Patch 3Com AP MOde:3CRWE454G72
97 // We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp.
98 //
99 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction);
100 StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT, (STATE_MACHINE_FUNC)AssocTimeoutAction);
101
102 // third column
103 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
104 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
105 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
106 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
107 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction);
108 //
109 // Patch, AP doesn't send Reassociate Rsp frame to Station.
110 //
111 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction);
112 StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT, (STATE_MACHINE_FUNC)ReassocTimeoutAction);
113
114 // fourth column
115 StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
116 StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
117 StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
118 StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
119 StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT, (STATE_MACHINE_FUNC)DisassocTimeoutAction);
120
121 // initialize the timer
122 RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer, GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE);
123 RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer, GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE);
124 RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer, GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE);
125}
126
127/*
128 ==========================================================================
129 Description:
130 Association timeout procedure. After association timeout, this function
131 will be called and it will put a message into the MLME queue
132 Parameters:
133 Standard timer parameters
134
135 IRQL = DISPATCH_LEVEL
136
137 ==========================================================================
138 */
139VOID AssocTimeout(IN PVOID SystemSpecific1,
140 IN PVOID FunctionContext,
141 IN PVOID SystemSpecific2,
142 IN PVOID SystemSpecific3)
143{
144 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
145
146 // Do nothing if the driver is starting halt state.
147 // This might happen when timer already been fired before cancel timer with mlmehalt
148 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
149 return;
150
151 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_ASSOC_TIMEOUT, 0, NULL);
152 RT28XX_MLME_HANDLER(pAd);
153}
154
155/*
156 ==========================================================================
157 Description:
158 Reassociation timeout procedure. After reassociation timeout, this
159 function will be called and put a message into the MLME queue
160 Parameters:
161 Standard timer parameters
162
163 IRQL = DISPATCH_LEVEL
164
165 ==========================================================================
166 */
167VOID ReassocTimeout(IN PVOID SystemSpecific1,
168 IN PVOID FunctionContext,
169 IN PVOID SystemSpecific2,
170 IN PVOID SystemSpecific3)
171{
172 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
173
174 // Do nothing if the driver is starting halt state.
175 // This might happen when timer already been fired before cancel timer with mlmehalt
176 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
177 return;
178
179 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_REASSOC_TIMEOUT, 0, NULL);
180 RT28XX_MLME_HANDLER(pAd);
181}
182
183/*
184 ==========================================================================
185 Description:
186 Disassociation timeout procedure. After disassociation timeout, this
187 function will be called and put a message into the MLME queue
188 Parameters:
189 Standard timer parameters
190
191 IRQL = DISPATCH_LEVEL
192
193 ==========================================================================
194 */
195VOID DisassocTimeout(IN PVOID SystemSpecific1,
196 IN PVOID FunctionContext,
197 IN PVOID SystemSpecific2,
198 IN PVOID SystemSpecific3)
199{
200 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
201
202 // Do nothing if the driver is starting halt state.
203 // This might happen when timer already been fired before cancel timer with mlmehalt
204 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
205 return;
206
207 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_DISASSOC_TIMEOUT, 0, NULL);
208 RT28XX_MLME_HANDLER(pAd);
209}
210
211/*
212 ==========================================================================
213 Description:
214 mlme assoc req handling procedure
215 Parameters:
216 Adapter - Adapter pointer
217 Elem - MLME Queue Element
218 Pre:
219 the station has been authenticated and the following information is stored in the config
220 -# SSID
221 -# supported rates and their length
222 -# listen interval (Adapter->StaCfg.default_listen_count)
223 -# Transmit power (Adapter->StaCfg.tx_power)
224 Post :
225 -# An association request frame is generated and sent to the air
226 -# Association timer starts
227 -# Association state -> ASSOC_WAIT_RSP
228
229 IRQL = DISPATCH_LEVEL
230
231 ==========================================================================
232 */
233VOID MlmeAssocReqAction(
234 IN PRTMP_ADAPTER pAd,
235 IN MLME_QUEUE_ELEM *Elem)
236{
237 UCHAR ApAddr[6];
238 HEADER_802_11 AssocHdr;
239 UCHAR Ccx2Len = 5;
240 UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
241 USHORT ListenIntv;
242 ULONG Timeout;
243 USHORT CapabilityInfo;
244 BOOLEAN TimerCancelled;
245 PUCHAR pOutBuffer = NULL;
246 NDIS_STATUS NStatus;
247 ULONG FrameLen = 0;
248 ULONG tmp;
249 USHORT VarIesOffset;
250 UCHAR CkipFlag;
251 UCHAR CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH];
252 UCHAR AironetCkipIe = IE_AIRONET_CKIP;
253 UCHAR AironetCkipLen = CKIP_NEGOTIATION_LENGTH;
254 UCHAR AironetIPAddressIE = IE_AIRONET_IPADDRESS;
255 UCHAR AironetIPAddressLen = AIRONET_IPADDRESS_LENGTH;
256 UCHAR AironetIPAddressBuffer[AIRONET_IPADDRESS_LENGTH] = {0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00};
257 USHORT Status;
258
259 // Block all authentication request durning WPA block period
260 if (pAd->StaCfg.bBlockAssoc == TRUE)
261 {
262 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block Assoc request durning WPA block period!\n"));
263 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
264 Status = MLME_STATE_MACHINE_REJECT;
265 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
266 }
267 // check sanity first
268 else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv))
269 {
270 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled);
271 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr);
272
273 // Get an unused nonpaged memory
274 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
275 if (NStatus != NDIS_STATUS_SUCCESS)
276 {
277 DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() allocate memory failed \n"));
278 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
279 Status = MLME_FAIL_NO_RESOURCE;
280 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
281 return;
282 }
283
284 // Add by James 03/06/27
285 pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
286 // Association don't need to report MAC address
287 pAd->StaCfg.AssocInfo.AvailableRequestFixedIEs =
288 NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL;
289 pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo;
290 pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv;
291 // Only reassociate need this
292 //COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr);
293 pAd->StaCfg.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
294
295 NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN);
296 // First add SSID
297 VarIesOffset = 0;
298 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe, 1);
299 VarIesOffset += 1;
300 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1);
301 VarIesOffset += 1;
302 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
303 VarIesOffset += pAd->MlmeAux.SsidLen;
304
305 // Second add Supported rates
306 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe, 1);
307 VarIesOffset += 1;
308 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1);
309 VarIesOffset += 1;
310 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen);
311 VarIesOffset += pAd->MlmeAux.SupRateLen;
312 // End Add by James
313
314 if ((pAd->CommonCfg.Channel > 14) &&
315 (pAd->CommonCfg.bIEEE80211H == TRUE))
316 CapabilityInfo |= 0x0100;
317
318 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send ASSOC request...\n"));
319 MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr);
320
321 // Build basic frame first
322 MakeOutgoingFrame(pOutBuffer, &FrameLen,
323 sizeof(HEADER_802_11), &AssocHdr,
324 2, &CapabilityInfo,
325 2, &ListenIntv,
326 1, &SsidIe,
327 1, &pAd->MlmeAux.SsidLen,
328 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid,
329 1, &SupRateIe,
330 1, &pAd->MlmeAux.SupRateLen,
331 pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
332 END_OF_ARGS);
333
334 if (pAd->MlmeAux.ExtRateLen != 0)
335 {
336 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
337 1, &ExtRateIe,
338 1, &pAd->MlmeAux.ExtRateLen,
339 pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate,
340 END_OF_ARGS);
341 FrameLen += tmp;
342 }
343
344 // HT
345 if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
346 {
347 ULONG TmpLen;
348 UCHAR HtLen;
349 UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
350 if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE)
351 {
352 HtLen = SIZE_HT_CAP_IE + 4;
353 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
354 1, &WpaIe,
355 1, &HtLen,
356 4, &BROADCOM[0],
357 pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
358 END_OF_ARGS);
359 }
360 else
361 {
362 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
363 1, &HtCapIe,
364 1, &pAd->MlmeAux.HtCapabilityLen,
365 pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
366 END_OF_ARGS);
367 }
368 FrameLen += TmpLen;
369 }
370
371 // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION
372 // Case I: (Aggregation + Piggy-Back)
373 // 1. user enable aggregation, AND
374 // 2. Mac support piggy-back
375 // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON
376 // Case II: (Aggregation)
377 // 1. user enable aggregation, AND
378 // 2. AP annouces it's AGGREGATION-capable in BEACON
379 if (pAd->CommonCfg.bAggregationCapable)
380 {
381 if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3))
382 {
383 ULONG TmpLen;
384 UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00};
385 MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
386 9, RalinkIe,
387 END_OF_ARGS);
388 FrameLen += TmpLen;
389 }
390 else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
391 {
392 ULONG TmpLen;
393 UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00};
394 MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
395 9, RalinkIe,
396 END_OF_ARGS);
397 FrameLen += TmpLen;
398 }
399 }
400 else
401 {
402 ULONG TmpLen;
403 UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00};
404 MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
405 9, RalinkIe,
406 END_OF_ARGS);
407 FrameLen += TmpLen;
408 }
409
410 if (pAd->MlmeAux.APEdcaParm.bValid)
411 {
412 if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable)
413 {
414 QBSS_STA_INFO_PARM QosInfo;
415
416 NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM));
417 QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE;
418 QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK;
419 QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI;
420 QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO;
421 QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength;
422 WmeIe[8] |= *(PUCHAR)&QosInfo;
423 }
424 else
425 {
426 // The Parameter Set Count is set to ¡§0¡¨ in the association request frames
427 // WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f);
428 }
429
430 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
431 9, &WmeIe[0],
432 END_OF_ARGS);
433 FrameLen += tmp;
434 }
435
436 //
437 // Let WPA(#221) Element ID on the end of this association frame.
438 // Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp.
439 // For example: Put Vendor Specific IE on the front of WPA IE.
440 // This happens on AP (Model No:Linksys WRK54G)
441 //
442 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
443 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
444 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
445 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
446 )
447 )
448 {
449 UCHAR RSNIe = IE_WPA;
450
451 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
452 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2))
453 {
454 RSNIe = IE_WPA2;
455 }
456
457#ifdef RT30xx
458#ifdef SIOCSIWGENIE
459 if (pAd->StaCfg.WpaSupplicantUP != 1)
460#endif // SIOCSIWGENIE //
461#endif
462 RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0);
463
464 // Check for WPA PMK cache list
465 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
466 {
467 INT idx;
468 BOOLEAN FoundPMK = FALSE;
469 // Search chched PMKID, append it if existed
470 for (idx = 0; idx < PMKID_NO; idx++)
471 {
472 if (NdisEqualMemory(ApAddr, &pAd->StaCfg.SavedPMK[idx].BSSID, 6))
473 {
474 FoundPMK = TRUE;
475 break;
476 }
477 }
478
479 if (FoundPMK)
480 {
481 // Set PMK number
482 *(PUSHORT) &pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len] = 1;
483 NdisMoveMemory(&pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len + 2], &pAd->StaCfg.SavedPMK[idx].PMKID, 16);
484 pAd->StaCfg.RSNIE_Len += 18;
485 }
486 }
487
488#ifdef RT30xx
489#ifdef SIOCSIWGENIE
490 if (pAd->StaCfg.WpaSupplicantUP == 1)
491 {
492 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
493 pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
494 END_OF_ARGS);
495 }
496 else
497#endif
498#endif
499 {
500 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
501 1, &RSNIe,
502 1, &pAd->StaCfg.RSNIE_Len,
503 pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
504 END_OF_ARGS);
505 }
506
507 FrameLen += tmp;
508
509#ifdef RT30xx
510#ifdef SIOCSIWGENIE
511 if (pAd->StaCfg.WpaSupplicantUP != 1)
512#endif
513#endif
514 {
515 // Append Variable IE
516 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &RSNIe, 1);
517 VarIesOffset += 1;
518 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->StaCfg.RSNIE_Len, 1);
519 VarIesOffset += 1;
520 }
521 NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
522 VarIesOffset += pAd->StaCfg.RSNIE_Len;
523
524 // Set Variable IEs Length
525 pAd->StaCfg.ReqVarIELen = VarIesOffset;
526 }
527
528 // We have update that at PeerBeaconAtJoinRequest()
529 CkipFlag = pAd->StaCfg.CkipFlag;
530 if (CkipFlag != 0)
531 {
532 NdisZeroMemory(CkipNegotiationBuffer, CKIP_NEGOTIATION_LENGTH);
533 CkipNegotiationBuffer[2] = 0x66;
534 // Make it try KP & MIC, since we have to follow the result from AssocRsp
535 CkipNegotiationBuffer[8] = 0x18;
536 CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH - 1] = 0x22;
537 CkipFlag = 0x18;
538
539 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
540 1, &AironetCkipIe,
541 1, &AironetCkipLen,
542 AironetCkipLen, CkipNegotiationBuffer,
543 END_OF_ARGS);
544 FrameLen += tmp;
545 }
546
547 // Add CCX v2 request if CCX2 admin state is on
548 if (pAd->StaCfg.CCXControl.field.Enable == 1)
549 {
550
551 //
552 // Add AironetIPAddressIE for Cisco CCX 2.X
553 // Add CCX Version
554 //
555 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
556 1, &AironetIPAddressIE,
557 1, &AironetIPAddressLen,
558 AironetIPAddressLen, AironetIPAddressBuffer,
559 1, &Ccx2Ie,
560 1, &Ccx2Len,
561 Ccx2Len, Ccx2IeInfo,
562 END_OF_ARGS);
563 FrameLen += tmp;
564
565 // Add by James 03/06/27
566 // Set Variable IEs Length
567 pAd->StaCfg.ReqVarIELen = VarIesOffset;
568 pAd->StaCfg.AssocInfo.RequestIELength = VarIesOffset;
569
570 // OffsetResponseIEs follow ReqVarIE
571 pAd->StaCfg.AssocInfo.OffsetResponseIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAd->StaCfg.ReqVarIELen;
572 // End Add by James
573 }
574
575
576 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
577 MlmeFreeMemory(pAd, pOutBuffer);
578
579 RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout);
580 pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP;
581 }
582 else
583 {
584 DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n"));
585 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
586 Status = MLME_INVALID_FORMAT;
587 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
588 }
589
590}
591
592/*
593 ==========================================================================
594 Description:
595 mlme reassoc req handling procedure
596 Parameters:
597 Elem -
598 Pre:
599 -# SSID (Adapter->StaCfg.ssid[])
600 -# BSSID (AP address, Adapter->StaCfg.bssid)
601 -# Supported rates (Adapter->StaCfg.supported_rates[])
602 -# Supported rates length (Adapter->StaCfg.supported_rates_len)
603 -# Tx power (Adapter->StaCfg.tx_power)
604
605 IRQL = DISPATCH_LEVEL
606
607 ==========================================================================
608 */
609VOID MlmeReassocReqAction(
610 IN PRTMP_ADAPTER pAd,
611 IN MLME_QUEUE_ELEM *Elem)
612{
613 UCHAR ApAddr[6];
614 HEADER_802_11 ReassocHdr;
615 UCHAR Ccx2Len = 5;
616 UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
617 USHORT CapabilityInfo, ListenIntv;
618 ULONG Timeout;
619 ULONG FrameLen = 0;
620 BOOLEAN TimerCancelled;
621 NDIS_STATUS NStatus;
622 ULONG tmp;
623 PUCHAR pOutBuffer = NULL;
624 USHORT Status;
625
626 // Block all authentication request durning WPA block period
627 if (pAd->StaCfg.bBlockAssoc == TRUE)
628 {
629 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block ReAssoc request durning WPA block period!\n"));
630 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
631 Status = MLME_STATE_MACHINE_REJECT;
632 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
633 }
634 // the parameters are the same as the association
635 else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv))
636 {
637 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled);
638
639 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
640 if(NStatus != NDIS_STATUS_SUCCESS)
641 {
642 DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() allocate memory failed \n"));
643 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
644 Status = MLME_FAIL_NO_RESOURCE;
645 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
646 return;
647 }
648
649 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr);
650
651 // make frame, use bssid as the AP address??
652 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send RE-ASSOC request...\n"));
653 MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, ApAddr, ApAddr);
654 MakeOutgoingFrame(pOutBuffer, &FrameLen,
655 sizeof(HEADER_802_11), &ReassocHdr,
656 2, &CapabilityInfo,
657 2, &ListenIntv,
658 MAC_ADDR_LEN, ApAddr,
659 1, &SsidIe,
660 1, &pAd->MlmeAux.SsidLen,
661 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid,
662 1, &SupRateIe,
663 1, &pAd->MlmeAux.SupRateLen,
664 pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
665 END_OF_ARGS);
666
667 if (pAd->MlmeAux.ExtRateLen != 0)
668 {
669 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
670 1, &ExtRateIe,
671 1, &pAd->MlmeAux.ExtRateLen,
672 pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate,
673 END_OF_ARGS);
674 FrameLen += tmp;
675 }
676
677 if (pAd->MlmeAux.APEdcaParm.bValid)
678 {
679 if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable)
680 {
681 QBSS_STA_INFO_PARM QosInfo;
682
683 NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM));
684 QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE;
685 QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK;
686 QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI;
687 QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO;
688 QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength;
689 WmeIe[8] |= *(PUCHAR)&QosInfo;
690 }
691
692 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
693 9, &WmeIe[0],
694 END_OF_ARGS);
695 FrameLen += tmp;
696 }
697
698 // HT
699 if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
700 {
701 ULONG TmpLen;
702 UCHAR HtLen;
703 UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
704 if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE)
705 {
706 HtLen = SIZE_HT_CAP_IE + 4;
707 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
708 1, &WpaIe,
709 1, &HtLen,
710 4, &BROADCOM[0],
711 pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
712 END_OF_ARGS);
713 }
714 else
715 {
716 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
717 1, &HtCapIe,
718 1, &pAd->MlmeAux.HtCapabilityLen,
719 pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
720 END_OF_ARGS);
721 }
722 FrameLen += TmpLen;
723 }
724
725 // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION
726 // Case I: (Aggregation + Piggy-Back)
727 // 1. user enable aggregation, AND
728 // 2. Mac support piggy-back
729 // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON
730 // Case II: (Aggregation)
731 // 1. user enable aggregation, AND
732 // 2. AP annouces it's AGGREGATION-capable in BEACON
733 if (pAd->CommonCfg.bAggregationCapable)
734 {
735 if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3))
736 {
737 ULONG TmpLen;
738 UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00};
739 MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
740 9, RalinkIe,
741 END_OF_ARGS);
742 FrameLen += TmpLen;
743 }
744 else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
745 {
746 ULONG TmpLen;
747 UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00};
748 MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
749 9, RalinkIe,
750 END_OF_ARGS);
751 FrameLen += TmpLen;
752 }
753 }
754 else
755 {
756 ULONG TmpLen;
757 UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04, 0x00, 0x00, 0x00};
758 MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
759 9, RalinkIe,
760 END_OF_ARGS);
761 FrameLen += TmpLen;
762 }
763
764 // Add CCX v2 request if CCX2 admin state is on
765 if (pAd->StaCfg.CCXControl.field.Enable == 1)
766 {
767 //
768 // Add CCX Version
769 //
770 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
771 1, &Ccx2Ie,
772 1, &Ccx2Len,
773 Ccx2Len, Ccx2IeInfo,
774 END_OF_ARGS);
775 FrameLen += tmp;
776 }
777
778 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
779 MlmeFreeMemory(pAd, pOutBuffer);
780
781 RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); /* in mSec */
782 pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP;
783 }
784 else
785 {
786 DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n"));
787 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
788 Status = MLME_INVALID_FORMAT;
789 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
790 }
791}
792
793/*
794 ==========================================================================
795 Description:
796 Upper layer issues disassoc request
797 Parameters:
798 Elem -
799
800 IRQL = PASSIVE_LEVEL
801
802 ==========================================================================
803 */
804VOID MlmeDisassocReqAction(
805 IN PRTMP_ADAPTER pAd,
806 IN MLME_QUEUE_ELEM *Elem)
807{
808 PMLME_DISASSOC_REQ_STRUCT pDisassocReq;
809 HEADER_802_11 DisassocHdr;
810 PHEADER_802_11 pDisassocHdr;
811 PUCHAR pOutBuffer = NULL;
812 ULONG FrameLen = 0;
813 NDIS_STATUS NStatus;
814 BOOLEAN TimerCancelled;
815 ULONG Timeout = 0;
816 USHORT Status;
817
818 // skip sanity check
819 pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg);
820
821 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
822 if (NStatus != NDIS_STATUS_SUCCESS)
823 {
824 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n"));
825 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
826 Status = MLME_FAIL_NO_RESOURCE;
827 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
828 return;
829 }
830
831
832
833 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &TimerCancelled);
834
835 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n",
836 pDisassocReq->Addr[0], pDisassocReq->Addr[1], pDisassocReq->Addr[2],
837 pDisassocReq->Addr[3], pDisassocReq->Addr[4], pDisassocReq->Addr[5], pDisassocReq->Reason));
838 MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr); // patch peap ttls switching issue
839 MakeOutgoingFrame(pOutBuffer, &FrameLen,
840 sizeof(HEADER_802_11),&DisassocHdr,
841 2, &pDisassocReq->Reason,
842 END_OF_ARGS);
843 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
844
845 // To patch Instance and Buffalo(N) AP
846 // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine
847 // Therefore, we send both of them.
848 pDisassocHdr = (PHEADER_802_11)pOutBuffer;
849 pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH;
850 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
851
852 MlmeFreeMemory(pAd, pOutBuffer);
853
854 pAd->StaCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING;
855 COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pDisassocReq->Addr);
856
857 RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */
858 pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP;
859
860 {
861 union iwreq_data wrqu;
862 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
863 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
864 }
865}
866
867/*
868 ==========================================================================
869 Description:
870 peer sends assoc rsp back
871 Parameters:
872 Elme - MLME message containing the received frame
873
874 IRQL = DISPATCH_LEVEL
875
876 ==========================================================================
877 */
878VOID PeerAssocRspAction(
879 IN PRTMP_ADAPTER pAd,
880 IN MLME_QUEUE_ELEM *Elem)
881{
882 USHORT CapabilityInfo, Status, Aid;
883 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen;
884 UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen;
885 UCHAR Addr2[MAC_ADDR_LEN];
886 BOOLEAN TimerCancelled;
887 UCHAR CkipFlag;
888 EDCA_PARM EdcaParm;
889 HT_CAPABILITY_IE HtCapability;
890 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
891 UCHAR HtCapabilityLen;
892 UCHAR AddHtInfoLen;
893 UCHAR NewExtChannelOffset = 0xff;
894
895 if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen,
896 &HtCapability,&AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag))
897 {
898 // The frame is for me ?
899 if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid))
900 {
901 DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status));
902 DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n",Elem->Wcid, pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
903 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled);
904 if(Status == MLME_SUCCESS)
905 {
906 UCHAR MaxSupportedRateIn500Kbps = 0;
907 UCHAR idx;
908
909 // supported rates array may not be sorted. sort it and find the maximum rate
910 for (idx=0; idx<SupRateLen; idx++)
911 {
912 if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f))
913 MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f;
914 }
915
916 for (idx=0; idx<ExtRateLen; idx++)
917 {
918 if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f))
919 MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f;
920 }
921 // go to procedure listed on page 376
922 AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen,
923 &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo);
924
925 StaAddMacTableEntry(pAd, &pAd->MacTab.Content[BSSID_WCID], MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, CapabilityInfo);
926
927 pAd->StaCfg.CkipFlag = CkipFlag;
928 if (CkipFlag & 0x18)
929 {
930 NdisZeroMemory(pAd->StaCfg.TxSEQ, 4);
931 NdisZeroMemory(pAd->StaCfg.RxSEQ, 4);
932 NdisZeroMemory(pAd->StaCfg.CKIPMIC, 4);
933 pAd->StaCfg.GIV[0] = RandomByte(pAd);
934 pAd->StaCfg.GIV[1] = RandomByte(pAd);
935 pAd->StaCfg.GIV[2] = RandomByte(pAd);
936 pAd->StaCfg.bCkipOn = TRUE;
937 DBGPRINT(RT_DEBUG_TRACE, ("<CCX> pAd->StaCfg.CkipFlag = 0x%02x\n", pAd->StaCfg.CkipFlag));
938 }
939 }
940 else
941 {
942 }
943 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
944 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
945 }
946 }
947 else
948 {
949 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerAssocRspAction() sanity check fail\n"));
950 }
951}
952
953/*
954 ==========================================================================
955 Description:
956 peer sends reassoc rsp
957 Parametrs:
958 Elem - MLME message cntaining the received frame
959
960 IRQL = DISPATCH_LEVEL
961
962 ==========================================================================
963 */
964VOID PeerReassocRspAction(
965 IN PRTMP_ADAPTER pAd,
966 IN MLME_QUEUE_ELEM *Elem)
967{
968 USHORT CapabilityInfo;
969 USHORT Status;
970 USHORT Aid;
971 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen;
972 UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen;
973 UCHAR Addr2[MAC_ADDR_LEN];
974 UCHAR CkipFlag;
975 BOOLEAN TimerCancelled;
976 EDCA_PARM EdcaParm;
977 HT_CAPABILITY_IE HtCapability;
978 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
979 UCHAR HtCapabilityLen;
980 UCHAR AddHtInfoLen;
981 UCHAR NewExtChannelOffset = 0xff;
982
983 if(PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen,
984 &HtCapability, &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag))
985 {
986 if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) // The frame is for me ?
987 {
988 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - receive REASSOC_RSP to me (status=%d)\n", Status));
989 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled);
990
991 if(Status == MLME_SUCCESS)
992 {
993 // go to procedure listed on page 376
994 AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen,
995 &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo);
996
997 {
998 union iwreq_data wrqu;
999 wext_notify_event_assoc(pAd);
1000
1001 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1002 memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
1003 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1004
1005 }
1006
1007 }
1008
1009 {
1010 // CkipFlag is no use for reassociate
1011 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1012 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
1013 }
1014 }
1015 }
1016 else
1017 {
1018 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerReassocRspAction() sanity check fail\n"));
1019 }
1020
1021}
1022
1023/*
1024 ==========================================================================
1025 Description:
1026 procedures on IEEE 802.11/1999 p.376
1027 Parametrs:
1028
1029 IRQL = DISPATCH_LEVEL
1030
1031 ==========================================================================
1032 */
1033VOID AssocPostProc(
1034 IN PRTMP_ADAPTER pAd,
1035 IN PUCHAR pAddr2,
1036 IN USHORT CapabilityInfo,
1037 IN USHORT Aid,
1038 IN UCHAR SupRate[],
1039 IN UCHAR SupRateLen,
1040 IN UCHAR ExtRate[],
1041 IN UCHAR ExtRateLen,
1042 IN PEDCA_PARM pEdcaParm,
1043 IN HT_CAPABILITY_IE *pHtCapability,
1044 IN UCHAR HtCapabilityLen,
1045 IN ADD_HT_INFO_IE *pAddHtInfo) // AP might use this additional ht info IE
1046{
1047 ULONG Idx;
1048
1049 pAd->MlmeAux.BssType = BSS_INFRA;
1050 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAddr2);
1051 pAd->MlmeAux.Aid = Aid;
1052 pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
1053
1054 // Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on.
1055 if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE))
1056 {
1057 pEdcaParm->bValid = TRUE;
1058 pEdcaParm->Aifsn[0] = 3;
1059 pEdcaParm->Aifsn[1] = 7;
1060 pEdcaParm->Aifsn[2] = 2;
1061 pEdcaParm->Aifsn[3] = 2;
1062
1063 pEdcaParm->Cwmin[0] = 4;
1064 pEdcaParm->Cwmin[1] = 4;
1065 pEdcaParm->Cwmin[2] = 3;
1066 pEdcaParm->Cwmin[3] = 2;
1067
1068 pEdcaParm->Cwmax[0] = 10;
1069 pEdcaParm->Cwmax[1] = 10;
1070 pEdcaParm->Cwmax[2] = 4;
1071 pEdcaParm->Cwmax[3] = 3;
1072
1073 pEdcaParm->Txop[0] = 0;
1074 pEdcaParm->Txop[1] = 0;
1075 pEdcaParm->Txop[2] = 96;
1076 pEdcaParm->Txop[3] = 48;
1077
1078 }
1079
1080 NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
1081
1082 // filter out un-supported rates
1083 pAd->MlmeAux.SupRateLen = SupRateLen;
1084 NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
1085 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
1086
1087 // filter out un-supported rates
1088 pAd->MlmeAux.ExtRateLen = ExtRateLen;
1089 NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
1090 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
1091
1092 if (HtCapabilityLen > 0)
1093 {
1094 RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo);
1095 }
1096 DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
1097
1098 DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> (Mmps=%d, AmsduSize=%d, )\n",
1099 pAd->MacTab.Content[BSSID_WCID].MmpsMode, pAd->MacTab.Content[BSSID_WCID].AMsduSize));
1100
1101 // Set New WPA information
1102 Idx = BssTableSearch(&pAd->ScanTab, pAddr2, pAd->MlmeAux.Channel);
1103 if (Idx == BSS_NOT_FOUND)
1104 {
1105 DBGPRINT_ERR(("ASSOC - Can't find BSS after receiving Assoc response\n"));
1106 }
1107 else
1108 {
1109 // Init variable
1110 pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = 0;
1111 NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, MAX_LEN_OF_RSNIE);
1112
1113 // Store appropriate RSN_IE for WPA SM negotiation later
1114 if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0))
1115 {
1116 PUCHAR pVIE;
1117 USHORT len;
1118 PEID_STRUCT pEid;
1119
1120 pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs;
1121 len = pAd->ScanTab.BssEntry[Idx].VarIELen;
1122
1123 while (len > 0)
1124 {
1125 pEid = (PEID_STRUCT) pVIE;
1126 // For WPA/WPAPSK
1127 if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
1128 && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
1129 {
1130 NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2));
1131 pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2);
1132 DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n"));
1133 }
1134 // For WPA2/WPA2PSK
1135 else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
1136 && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
1137 {
1138 NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2));
1139 pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2);
1140 DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n"));
1141 }
1142
1143 pVIE += (pEid->Len + 2);
1144 len -= (pEid->Len + 2);
1145 }
1146 }
1147
1148 if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0)
1149 {
1150 DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> no RSN_IE \n"));
1151 }
1152 else
1153 {
1154 hex_dump("RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len);
1155 }
1156 }
1157}
1158
1159/*
1160 ==========================================================================
1161 Description:
1162 left part of IEEE 802.11/1999 p.374
1163 Parameters:
1164 Elem - MLME message containing the received frame
1165
1166 IRQL = DISPATCH_LEVEL
1167
1168 ==========================================================================
1169 */
1170VOID PeerDisassocAction(
1171 IN PRTMP_ADAPTER pAd,
1172 IN MLME_QUEUE_ELEM *Elem)
1173{
1174 UCHAR Addr2[MAC_ADDR_LEN];
1175 USHORT Reason;
1176
1177 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction()\n"));
1178 if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason))
1179 {
1180 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() Reason = %d\n", Reason));
1181 if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2))
1182 {
1183
1184 if (pAd->CommonCfg.bWirelessEvent)
1185 {
1186 RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1187 }
1188
1189 //
1190 // Get Current System time and Turn on AdjacentAPReport
1191 //
1192 NdisGetSystemUpTime(&pAd->StaCfg.CCXAdjacentAPLinkDownTime);
1193 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1194 LinkDown(pAd, TRUE);
1195 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1196
1197 {
1198 union iwreq_data wrqu;
1199 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1200 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1201 }
1202 }
1203 }
1204 else
1205 {
1206 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() sanity check fail\n"));
1207 }
1208
1209}
1210
1211/*
1212 ==========================================================================
1213 Description:
1214 what the state machine will do after assoc timeout
1215 Parameters:
1216 Elme -
1217
1218 IRQL = DISPATCH_LEVEL
1219
1220 ==========================================================================
1221 */
1222VOID AssocTimeoutAction(
1223 IN PRTMP_ADAPTER pAd,
1224 IN MLME_QUEUE_ELEM *Elem)
1225{
1226 USHORT Status;
1227 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - AssocTimeoutAction\n"));
1228 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1229 Status = MLME_REJ_TIMEOUT;
1230 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
1231}
1232
1233/*
1234 ==========================================================================
1235 Description:
1236 what the state machine will do after reassoc timeout
1237
1238 IRQL = DISPATCH_LEVEL
1239
1240 ==========================================================================
1241 */
1242VOID ReassocTimeoutAction(
1243 IN PRTMP_ADAPTER pAd,
1244 IN MLME_QUEUE_ELEM *Elem)
1245{
1246 USHORT Status;
1247 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - ReassocTimeoutAction\n"));
1248 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1249 Status = MLME_REJ_TIMEOUT;
1250 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
1251}
1252
1253/*
1254 ==========================================================================
1255 Description:
1256 what the state machine will do after disassoc timeout
1257
1258 IRQL = DISPATCH_LEVEL
1259
1260 ==========================================================================
1261 */
1262VOID DisassocTimeoutAction(
1263 IN PRTMP_ADAPTER pAd,
1264 IN MLME_QUEUE_ELEM *Elem)
1265{
1266 USHORT Status;
1267 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - DisassocTimeoutAction\n"));
1268 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1269 Status = MLME_SUCCESS;
1270 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
1271}
1272
1273VOID InvalidStateWhenAssoc(
1274 IN PRTMP_ADAPTER pAd,
1275 IN MLME_QUEUE_ELEM *Elem)
1276{
1277 USHORT Status;
1278 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n",
1279 pAd->Mlme.AssocMachine.CurrState));
1280 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1281 Status = MLME_STATE_MACHINE_REJECT;
1282 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
1283}
1284
1285VOID InvalidStateWhenReassoc(
1286 IN PRTMP_ADAPTER pAd,
1287 IN MLME_QUEUE_ELEM *Elem)
1288{
1289 USHORT Status;
1290 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n",
1291 pAd->Mlme.AssocMachine.CurrState));
1292 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1293 Status = MLME_STATE_MACHINE_REJECT;
1294 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
1295}
1296
1297VOID InvalidStateWhenDisassociate(
1298 IN PRTMP_ADAPTER pAd,
1299 IN MLME_QUEUE_ELEM *Elem)
1300{
1301 USHORT Status;
1302 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n",
1303 pAd->Mlme.AssocMachine.CurrState));
1304 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
1305 Status = MLME_STATE_MACHINE_REJECT;
1306 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
1307}
1308
1309/*
1310 ==========================================================================
1311 Description:
1312 right part of IEEE 802.11/1999 page 374
1313 Note:
1314 This event should never cause ASSOC state machine perform state
1315 transition, and has no relationship with CNTL machine. So we separate
1316 this routine as a service outside of ASSOC state transition table.
1317
1318 IRQL = DISPATCH_LEVEL
1319
1320 ==========================================================================
1321 */
1322VOID Cls3errAction(
1323 IN PRTMP_ADAPTER pAd,
1324 IN PUCHAR pAddr)
1325{
1326 HEADER_802_11 DisassocHdr;
1327 PHEADER_802_11 pDisassocHdr;
1328 PUCHAR pOutBuffer = NULL;
1329 ULONG FrameLen = 0;
1330 NDIS_STATUS NStatus;
1331 USHORT Reason = REASON_CLS3ERR;
1332
1333 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1334 if (NStatus != NDIS_STATUS_SUCCESS)
1335 return;
1336
1337 DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Class 3 Error, Send DISASSOC frame\n"));
1338 MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, pAd->CommonCfg.Bssid); // patch peap ttls switching issue
1339 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1340 sizeof(HEADER_802_11),&DisassocHdr,
1341 2, &Reason,
1342 END_OF_ARGS);
1343 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1344
1345 // To patch Instance and Buffalo(N) AP
1346 // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine
1347 // Therefore, we send both of them.
1348 pDisassocHdr = (PHEADER_802_11)pOutBuffer;
1349 pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH;
1350 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1351
1352 MlmeFreeMemory(pAd, pOutBuffer);
1353
1354 pAd->StaCfg.DisassocReason = REASON_CLS3ERR;
1355 COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pAddr);
1356}
1357
1358 /*
1359 ==========================================================================
1360 Description:
1361 Switch between WEP and CKIP upon new association up.
1362 Parameters:
1363
1364 IRQL = DISPATCH_LEVEL
1365
1366 ==========================================================================
1367 */
1368VOID SwitchBetweenWepAndCkip(
1369 IN PRTMP_ADAPTER pAd)
1370{
1371 int i;
1372 SHAREDKEY_MODE_STRUC csr1;
1373
1374 // if KP is required. change the CipherAlg in hardware shard key table from WEP
1375 // to CKIP. else remain as WEP
1376 if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10))
1377 {
1378 // modify hardware key table so that MAC use correct algorithm to decrypt RX
1379 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word);
1380 if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP64)
1381 csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP64;
1382 else if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP128)
1383 csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP128;
1384
1385 if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP64)
1386 csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP64;
1387 else if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP128)
1388 csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP128;
1389
1390 if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP64)
1391 csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP64;
1392 else if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP128)
1393 csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP128;
1394
1395 if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP64)
1396 csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP64;
1397 else if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP128)
1398 csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP128;
1399 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word);
1400 DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg]));
1401
1402 // modify software key table so that driver can specify correct algorithm in TXD upon TX
1403 for (i=0; i<SHARE_KEY_NUM; i++)
1404 {
1405 if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_WEP64)
1406 pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP64;
1407 else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_WEP128)
1408 pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP128;
1409 }
1410 }
1411
1412 // else if KP NOT inused. change the CipherAlg in hardware shard key table from CKIP
1413 // to WEP.
1414 else
1415 {
1416 // modify hardware key table so that MAC use correct algorithm to decrypt RX
1417 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word);
1418 if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP64)
1419 csr1.field.Bss0Key0CipherAlg = CIPHER_WEP64;
1420 else if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP128)
1421 csr1.field.Bss0Key0CipherAlg = CIPHER_WEP128;
1422
1423 if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP64)
1424 csr1.field.Bss0Key1CipherAlg = CIPHER_WEP64;
1425 else if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP128)
1426 csr1.field.Bss0Key1CipherAlg = CIPHER_WEP128;
1427
1428 if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP64)
1429 csr1.field.Bss0Key2CipherAlg = CIPHER_WEP64;
1430 else if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP128)
1431 csr1.field.Bss0Key2CipherAlg = CIPHER_WEP128;
1432
1433 if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP64)
1434 csr1.field.Bss0Key3CipherAlg = CIPHER_WEP64;
1435 else if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP128)
1436 csr1.field.Bss0Key3CipherAlg = CIPHER_WEP128;
1437
1438 // modify software key table so that driver can specify correct algorithm in TXD upon TX
1439 for (i=0; i<SHARE_KEY_NUM; i++)
1440 {
1441 if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_CKIP64)
1442 pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP64;
1443 else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_CKIP128)
1444 pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP128;
1445 }
1446
1447 //
1448 // On WPA-NONE, must update CipherAlg.
1449 // Because the OID_802_11_WEP_STATUS was been set after OID_802_11_ADD_KEY
1450 // and CipherAlg will be CIPHER_NONE by Windows ZeroConfig.
1451 // So we need to update CipherAlg after connect.
1452 //
1453 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
1454 {
1455 for (i = 0; i < SHARE_KEY_NUM; i++)
1456 {
1457 if (pAd->SharedKey[BSS0][i].KeyLen != 0)
1458 {
1459 if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)
1460 {
1461 pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_TKIP;
1462 }
1463 else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1464 {
1465 pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_AES;
1466 }
1467 }
1468 else
1469 {
1470 pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE;
1471 }
1472 }
1473
1474 csr1.field.Bss0Key0CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1475 csr1.field.Bss0Key1CipherAlg = pAd->SharedKey[BSS0][1].CipherAlg;
1476 csr1.field.Bss0Key2CipherAlg = pAd->SharedKey[BSS0][2].CipherAlg;
1477 csr1.field.Bss0Key3CipherAlg = pAd->SharedKey[BSS0][3].CipherAlg;
1478 }
1479 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word);
1480 DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg]));
1481 }
1482}
1483
1484int wext_notify_event_assoc(
1485 IN RTMP_ADAPTER *pAd)
1486{
1487 union iwreq_data wrqu;
1488 char custom[IW_CUSTOM_MAX] = {0};
1489
1490#if WIRELESS_EXT > 17
1491 if (pAd->StaCfg.ReqVarIELen <= IW_CUSTOM_MAX)
1492 {
1493 wrqu.data.length = pAd->StaCfg.ReqVarIELen;
1494 memcpy(custom, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen);
1495 wireless_send_event(pAd->net_dev, IWEVASSOCREQIE, &wrqu, custom);
1496 }
1497 else
1498 DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n"));
1499#else
1500 if (((pAd->StaCfg.ReqVarIELen*2) + 17) <= IW_CUSTOM_MAX)
1501 {
1502 UCHAR idx;
1503 wrqu.data.length = (pAd->StaCfg.ReqVarIELen*2) + 17;
1504 sprintf(custom, "ASSOCINFO(ReqIEs=");
1505 for (idx=0; idx<pAd->StaCfg.ReqVarIELen; idx++)
1506 sprintf(custom + strlen(custom), "%02x", pAd->StaCfg.ReqVarIEs[idx]);
1507 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom);
1508 }
1509 else
1510 DBGPRINT(RT_DEBUG_TRACE, ("(pAd->StaCfg.ReqVarIELen*2) + 17 > MAX_CUSTOM_LEN\n"));
1511#endif
1512
1513 return 0;
1514
1515}
1516
1517BOOLEAN StaAddMacTableEntry(
1518 IN PRTMP_ADAPTER pAd,
1519 IN PMAC_TABLE_ENTRY pEntry,
1520 IN UCHAR MaxSupportedRateIn500Kbps,
1521 IN HT_CAPABILITY_IE *pHtCapability,
1522 IN UCHAR HtCapabilityLen,
1523 IN USHORT CapabilityInfo)
1524{
1525 UCHAR MaxSupportedRate = RATE_11;
1526
1527 if (ADHOC_ON(pAd))
1528 CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
1529
1530 switch (MaxSupportedRateIn500Kbps)
1531 {
1532 case 108: MaxSupportedRate = RATE_54; break;
1533 case 96: MaxSupportedRate = RATE_48; break;
1534 case 72: MaxSupportedRate = RATE_36; break;
1535 case 48: MaxSupportedRate = RATE_24; break;
1536 case 36: MaxSupportedRate = RATE_18; break;
1537 case 24: MaxSupportedRate = RATE_12; break;
1538 case 18: MaxSupportedRate = RATE_9; break;
1539 case 12: MaxSupportedRate = RATE_6; break;
1540 case 22: MaxSupportedRate = RATE_11; break;
1541 case 11: MaxSupportedRate = RATE_5_5; break;
1542 case 4: MaxSupportedRate = RATE_2; break;
1543 case 2: MaxSupportedRate = RATE_1; break;
1544 default: MaxSupportedRate = RATE_11; break;
1545 }
1546
1547 if ((pAd->CommonCfg.PhyMode == PHY_11G) && (MaxSupportedRate < RATE_FIRST_OFDM_RATE))
1548 return FALSE;
1549
1550 // 11n only
1551 if (((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G))&& (HtCapabilityLen == 0))
1552 return FALSE;
1553
1554 if (!pEntry)
1555 return FALSE;
1556
1557 NdisAcquireSpinLock(&pAd->MacTabLock);
1558 if (pEntry)
1559 {
1560 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1561 if ((MaxSupportedRate < RATE_FIRST_OFDM_RATE) ||
1562 (pAd->CommonCfg.PhyMode == PHY_11B))
1563 {
1564 pEntry->RateLen = 4;
1565 if (MaxSupportedRate >= RATE_FIRST_OFDM_RATE)
1566 MaxSupportedRate = RATE_11;
1567 }
1568 else
1569 pEntry->RateLen = 12;
1570
1571 pEntry->MaxHTPhyMode.word = 0;
1572 pEntry->MinHTPhyMode.word = 0;
1573 pEntry->HTPhyMode.word = 0;
1574 pEntry->MaxSupportedRate = MaxSupportedRate;
1575 if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
1576 {
1577 pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
1578 pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
1579 pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
1580 pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
1581 pEntry->HTPhyMode.field.MODE = MODE_CCK;
1582 pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
1583 }
1584 else
1585 {
1586 pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
1587 pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
1588 pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
1589 pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
1590 pEntry->HTPhyMode.field.MODE = MODE_OFDM;
1591 pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
1592 }
1593 pEntry->CapabilityInfo = CapabilityInfo;
1594 CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE);
1595 CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE);
1596 }
1597
1598 // If this Entry supports 802.11n, upgrade to HT rate.
1599 if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
1600 {
1601 UCHAR j, bitmask; //k,bitmask;
1602 CHAR i;
1603
1604 if (ADHOC_ON(pAd))
1605 CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
1606 if ((pHtCapability->HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
1607 {
1608 pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
1609 }
1610 else
1611 {
1612 pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
1613 pAd->MacTab.fAnyStationNonGF = TRUE;
1614 pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
1615 }
1616
1617 if ((pHtCapability->HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
1618 {
1619 pEntry->MaxHTPhyMode.field.BW= BW_40;
1620 pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40));
1621 }
1622 else
1623 {
1624 pEntry->MaxHTPhyMode.field.BW = BW_20;
1625 pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pHtCapability->HtCapInfo.ShortGIfor20));
1626 pAd->MacTab.fAnyStation20Only = TRUE;
1627 }
1628
1629 // 3*3
1630 if (pAd->MACVersion >= RALINK_2883_VERSION && pAd->MACVersion < RALINK_3070_VERSION)
1631 pEntry->MaxHTPhyMode.field.TxBF = pAd->CommonCfg.RegTransmitSetting.field.TxBF;
1632
1633 // find max fixed rate
1634 for (i=23; i>=0; i--) // 3*3
1635 {
1636 j = i/8;
1637 bitmask = (1<<(i-(j*8)));
1638 if ((pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pHtCapability->MCSSet[j] & bitmask))
1639 {
1640 pEntry->MaxHTPhyMode.field.MCS = i;
1641 break;
1642 }
1643 if (i==0)
1644 break;
1645 }
1646
1647
1648 if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
1649 {
1650 if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
1651 {
1652 // Fix MCS as HT Duplicated Mode
1653 pEntry->MaxHTPhyMode.field.BW = 1;
1654 pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
1655 pEntry->MaxHTPhyMode.field.STBC = 0;
1656 pEntry->MaxHTPhyMode.field.ShortGI = 0;
1657 pEntry->MaxHTPhyMode.field.MCS = 32;
1658 }
1659 else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
1660 {
1661 // STA supports fixed MCS
1662 pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1663 }
1664 }
1665
1666 pEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
1667 pEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity;
1668 pEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor;
1669 pEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs;
1670 pEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize;
1671 pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
1672
1673 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE))
1674 CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED);
1675 if (pHtCapability->HtCapInfo.ShortGIfor20)
1676 CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
1677 if (pHtCapability->HtCapInfo.ShortGIfor40)
1678 CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
1679 if (pHtCapability->HtCapInfo.TxSTBC)
1680 CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
1681 if (pHtCapability->HtCapInfo.RxSTBC)
1682 CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
1683 if (pHtCapability->ExtHtCapInfo.PlusHTC)
1684 CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
1685 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
1686 CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
1687 if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03)
1688 CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
1689 }
1690 else
1691 {
1692 pAd->MacTab.fAnyStationIsLegacy = TRUE;
1693 }
1694
1695 NdisMoveMemory(&pEntry->HTCapability, pHtCapability, sizeof(HT_CAPABILITY_IE));
1696
1697 pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
1698 pEntry->CurrTxRate = pEntry->MaxSupportedRate;
1699
1700 // Set asic auto fall back
1701 if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1702 {
1703 PUCHAR pTable;
1704 UCHAR TableSize = 0;
1705
1706 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
1707 pEntry->bAutoTxRateSwitch = TRUE;
1708 }
1709 else
1710 {
1711 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1712 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1713 pEntry->bAutoTxRateSwitch = FALSE;
1714
1715 // If the legacy mode is set, overwrite the transmit setting of this entry.
1716 RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
1717 }
1718
1719 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1720 pEntry->Sst = SST_ASSOC;
1721 pEntry->AuthState = AS_AUTH_OPEN;
1722 pEntry->AuthMode = pAd->StaCfg.AuthMode;
1723 pEntry->WepStatus = pAd->StaCfg.WepStatus;
1724
1725 NdisReleaseSpinLock(&pAd->MacTabLock);
1726
1727 {
1728 union iwreq_data wrqu;
1729 wext_notify_event_assoc(pAd);
1730
1731 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1732 memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
1733 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1734
1735 }
1736 return TRUE;
1737}
1738
1739
diff --git a/drivers/staging/rt2870/sta/auth.c b/drivers/staging/rt2870/sta/auth.c
index d8414eac42f8..57632f9ec784 100644
--- a/drivers/staging/rt2870/sta/auth.c
+++ b/drivers/staging/rt2870/sta/auth.c
@@ -1,460 +1 @@
1/* #include "../../rt2860/sta/auth.c"
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 auth.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 John 2004-9-3 porting from RT2500
36*/
37#include "../rt_config.h"
38
39/*
40 ==========================================================================
41 Description:
42 authenticate state machine init, including state transition and timer init
43 Parameters:
44 Sm - pointer to the auth state machine
45 Note:
46 The state machine looks like this
47
48 AUTH_REQ_IDLE AUTH_WAIT_SEQ2 AUTH_WAIT_SEQ4
49 MT2_MLME_AUTH_REQ mlme_auth_req_action invalid_state_when_auth invalid_state_when_auth
50 MT2_PEER_AUTH_EVEN drop peer_auth_even_at_seq2_action peer_auth_even_at_seq4_action
51 MT2_AUTH_TIMEOUT Drop auth_timeout_action auth_timeout_action
52
53 IRQL = PASSIVE_LEVEL
54
55 ==========================================================================
56 */
57
58void AuthStateMachineInit(
59 IN PRTMP_ADAPTER pAd,
60 IN STATE_MACHINE *Sm,
61 OUT STATE_MACHINE_FUNC Trans[])
62{
63 StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_REQ_IDLE, AUTH_MACHINE_BASE);
64
65 // the first column
66 StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)MlmeAuthReqAction);
67
68 // the second column
69 StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth);
70 StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq2Action);
71 StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction);
72
73 // the third column
74 StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth);
75 StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq4Action);
76 StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction);
77
78 RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE);
79}
80
81/*
82 ==========================================================================
83 Description:
84 function to be executed at timer thread when auth timer expires
85
86 IRQL = DISPATCH_LEVEL
87
88 ==========================================================================
89 */
90VOID AuthTimeout(
91 IN PVOID SystemSpecific1,
92 IN PVOID FunctionContext,
93 IN PVOID SystemSpecific2,
94 IN PVOID SystemSpecific3)
95{
96 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
97
98 DBGPRINT(RT_DEBUG_TRACE,("AUTH - AuthTimeout\n"));
99
100 // Do nothing if the driver is starting halt state.
101 // This might happen when timer already been fired before cancel timer with mlmehalt
102 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
103 return;
104
105 // send a de-auth to reset AP's state machine (Patch AP-Dir635)
106 if (pAd->Mlme.AuthMachine.CurrState == AUTH_WAIT_SEQ2)
107 Cls2errAction(pAd, pAd->MlmeAux.Bssid);
108
109
110 MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL);
111 RT28XX_MLME_HANDLER(pAd);
112}
113
114
115/*
116 ==========================================================================
117 Description:
118
119 IRQL = DISPATCH_LEVEL
120
121 ==========================================================================
122 */
123VOID MlmeAuthReqAction(
124 IN PRTMP_ADAPTER pAd,
125 IN MLME_QUEUE_ELEM *Elem)
126{
127 UCHAR Addr[6];
128 USHORT Alg, Seq, Status;
129 ULONG Timeout;
130 HEADER_802_11 AuthHdr;
131 BOOLEAN TimerCancelled;
132 NDIS_STATUS NStatus;
133 PUCHAR pOutBuffer = NULL;
134 ULONG FrameLen = 0;
135
136 // Block all authentication request durning WPA block period
137 if (pAd->StaCfg.bBlockAssoc == TRUE)
138 {
139 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Block Auth request durning WPA block period!\n"));
140 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
141 Status = MLME_STATE_MACHINE_REJECT;
142 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
143 }
144 else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg))
145 {
146 // reset timer
147 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
148 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr);
149 pAd->MlmeAux.Alg = Alg;
150 Seq = 1;
151 Status = MLME_SUCCESS;
152
153 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
154 if(NStatus != NDIS_STATUS_SUCCESS)
155 {
156 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", Alg));
157 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
158 Status = MLME_FAIL_NO_RESOURCE;
159 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
160 return;
161 }
162
163 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#1 (Alg=%d)...\n", Alg));
164 MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid);
165 MakeOutgoingFrame(pOutBuffer, &FrameLen,
166 sizeof(HEADER_802_11),&AuthHdr,
167 2, &Alg,
168 2, &Seq,
169 2, &Status,
170 END_OF_ARGS);
171 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
172 MlmeFreeMemory(pAd, pOutBuffer);
173
174 RTMPSetTimer(&pAd->MlmeAux.AuthTimer, Timeout);
175 pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2;
176 }
177 else
178 {
179 DBGPRINT_ERR(("AUTH - MlmeAuthReqAction() sanity check failed\n"));
180 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
181 Status = MLME_INVALID_FORMAT;
182 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
183 }
184}
185
186/*
187 ==========================================================================
188 Description:
189
190 IRQL = DISPATCH_LEVEL
191
192 ==========================================================================
193 */
194VOID PeerAuthRspAtSeq2Action(
195 IN PRTMP_ADAPTER pAd,
196 IN MLME_QUEUE_ELEM *Elem)
197{
198 UCHAR Addr2[MAC_ADDR_LEN];
199 USHORT Seq, Status, RemoteStatus, Alg;
200 UCHAR ChlgText[CIPHER_TEXT_LEN];
201 UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8];
202 UCHAR Element[2];
203 HEADER_802_11 AuthHdr;
204 BOOLEAN TimerCancelled;
205 PUCHAR pOutBuffer = NULL;
206 NDIS_STATUS NStatus;
207 ULONG FrameLen = 0;
208 USHORT Status2;
209
210 if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
211 {
212 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2)
213 {
214 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status));
215 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
216
217 if (Status == MLME_SUCCESS)
218 {
219 // Authentication Mode "LEAP" has allow for CCX 1.X
220 if ((pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen)
221 )
222 {
223 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
224 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
225 }
226 else
227 {
228 // 2. shared key, need to be challenged
229 Seq++;
230 RemoteStatus = MLME_SUCCESS;
231
232 // Get an unused nonpaged memory
233 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
234 if(NStatus != NDIS_STATUS_SUCCESS)
235 {
236 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n"));
237 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
238 Status2 = MLME_FAIL_NO_RESOURCE;
239 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2);
240 return;
241 }
242
243 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n"));
244 MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid);
245 AuthHdr.FC.Wep = 1;
246 // Encrypt challenge text & auth information
247 RTMPInitWepEngine(
248 pAd,
249 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
250 pAd->StaCfg.DefaultKeyId,
251 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen,
252 CyperChlgText);
253
254 Alg = cpu2le16(*(USHORT *)&Alg);
255 Seq = cpu2le16(*(USHORT *)&Seq);
256 RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus);
257
258 RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2);
259 RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2);
260 RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2);
261 Element[0] = 16;
262 Element[1] = 128;
263 RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2);
264 RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128);
265 RTMPSetICV(pAd, CyperChlgText + 140);
266 MakeOutgoingFrame(pOutBuffer, &FrameLen,
267 sizeof(HEADER_802_11), &AuthHdr,
268 CIPHER_TEXT_LEN + 16, CyperChlgText,
269 END_OF_ARGS);
270 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
271 MlmeFreeMemory(pAd, pOutBuffer);
272
273 RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT);
274 pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4;
275 }
276 }
277 else
278 {
279 pAd->StaCfg.AuthFailReason = Status;
280 COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
281 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
282 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
283 }
284 }
285 }
286 else
287 {
288 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n"));
289 }
290}
291
292/*
293 ==========================================================================
294 Description:
295
296 IRQL = DISPATCH_LEVEL
297
298 ==========================================================================
299 */
300VOID PeerAuthRspAtSeq4Action(
301 IN PRTMP_ADAPTER pAd,
302 IN MLME_QUEUE_ELEM *Elem)
303{
304 UCHAR Addr2[MAC_ADDR_LEN];
305 USHORT Alg, Seq, Status;
306 CHAR ChlgText[CIPHER_TEXT_LEN];
307 BOOLEAN TimerCancelled;
308
309 if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
310 {
311 if(MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4)
312 {
313 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#4 to me\n"));
314 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
315
316 if (Status != MLME_SUCCESS)
317 {
318 pAd->StaCfg.AuthFailReason = Status;
319 COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
320 }
321
322 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
323 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
324 }
325 }
326 else
327 {
328 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n"));
329 }
330}
331
332/*
333 ==========================================================================
334 Description:
335
336 IRQL = DISPATCH_LEVEL
337
338 ==========================================================================
339 */
340VOID MlmeDeauthReqAction(
341 IN PRTMP_ADAPTER pAd,
342 IN MLME_QUEUE_ELEM *Elem)
343{
344 MLME_DEAUTH_REQ_STRUCT *pInfo;
345 HEADER_802_11 DeauthHdr;
346 PUCHAR pOutBuffer = NULL;
347 NDIS_STATUS NStatus;
348 ULONG FrameLen = 0;
349 USHORT Status;
350
351 pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg;
352
353 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
354 if (NStatus != NDIS_STATUS_SUCCESS)
355 {
356 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeDeauthReqAction() allocate memory fail\n"));
357 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
358 Status = MLME_FAIL_NO_RESOURCE;
359 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
360 return;
361 }
362
363 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pInfo->Reason));
364 MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, pAd->MlmeAux.Bssid);
365 MakeOutgoingFrame(pOutBuffer, &FrameLen,
366 sizeof(HEADER_802_11),&DeauthHdr,
367 2, &pInfo->Reason,
368 END_OF_ARGS);
369 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
370 MlmeFreeMemory(pAd, pOutBuffer);
371
372 pAd->StaCfg.DeauthReason = pInfo->Reason;
373 COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr);
374 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
375 Status = MLME_SUCCESS;
376 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
377
378 // send wireless event - for deauthentication
379 if (pAd->CommonCfg.bWirelessEvent)
380 RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
381}
382
383/*
384 ==========================================================================
385 Description:
386
387 IRQL = DISPATCH_LEVEL
388
389 ==========================================================================
390 */
391VOID AuthTimeoutAction(
392 IN PRTMP_ADAPTER pAd,
393 IN MLME_QUEUE_ELEM *Elem)
394{
395 USHORT Status;
396 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n"));
397 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
398 Status = MLME_REJ_TIMEOUT;
399 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
400}
401
402/*
403 ==========================================================================
404 Description:
405
406 IRQL = DISPATCH_LEVEL
407
408 ==========================================================================
409 */
410VOID InvalidStateWhenAuth(
411 IN PRTMP_ADAPTER pAd,
412 IN MLME_QUEUE_ELEM *Elem)
413{
414 USHORT Status;
415 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", pAd->Mlme.AuthMachine.CurrState));
416 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
417 Status = MLME_STATE_MACHINE_REJECT;
418 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
419}
420
421/*
422 ==========================================================================
423 Description:
424 Some STA/AP
425 Note:
426 This action should never trigger AUTH state transition, therefore we
427 separate it from AUTH state machine, and make it as a standalone service
428
429 IRQL = DISPATCH_LEVEL
430
431 ==========================================================================
432 */
433VOID Cls2errAction(
434 IN PRTMP_ADAPTER pAd,
435 IN PUCHAR pAddr)
436{
437 HEADER_802_11 DeauthHdr;
438 PUCHAR pOutBuffer = NULL;
439 NDIS_STATUS NStatus;
440 ULONG FrameLen = 0;
441 USHORT Reason = REASON_CLS2ERR;
442
443 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
444 if (NStatus != NDIS_STATUS_SUCCESS)
445 return;
446
447 DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Class 2 error, Send DEAUTH frame...\n"));
448 MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, pAd->MlmeAux.Bssid);
449 MakeOutgoingFrame(pOutBuffer, &FrameLen,
450 sizeof(HEADER_802_11),&DeauthHdr,
451 2, &Reason,
452 END_OF_ARGS);
453 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
454 MlmeFreeMemory(pAd, pOutBuffer);
455
456 pAd->StaCfg.DeauthReason = Reason;
457 COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr);
458}
459
460
diff --git a/drivers/staging/rt2870/sta/auth_rsp.c b/drivers/staging/rt2870/sta/auth_rsp.c
index cc639b1c6c13..783e266d3e8f 100644
--- a/drivers/staging/rt2870/sta/auth_rsp.c
+++ b/drivers/staging/rt2870/sta/auth_rsp.c
@@ -1,148 +1 @@
1/* #include "../../rt2860/sta/auth_rsp.c"
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 auth_rsp.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 John 2004-10-1 copy from RT2560
36*/
37#include "../rt_config.h"
38
39/*
40 ==========================================================================
41 Description:
42 authentication state machine init procedure
43 Parameters:
44 Sm - the state machine
45
46 IRQL = PASSIVE_LEVEL
47
48 ==========================================================================
49 */
50VOID AuthRspStateMachineInit(
51 IN PRTMP_ADAPTER pAd,
52 IN PSTATE_MACHINE Sm,
53 IN STATE_MACHINE_FUNC Trans[])
54{
55 StateMachineInit(Sm, Trans, MAX_AUTH_RSP_STATE, MAX_AUTH_RSP_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_RSP_IDLE, AUTH_RSP_MACHINE_BASE);
56
57 // column 1
58 StateMachineSetAction(Sm, AUTH_RSP_IDLE, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction);
59
60 // column 2
61 StateMachineSetAction(Sm, AUTH_RSP_WAIT_CHAL, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction);
62
63}
64
65/*
66 ==========================================================================
67 Description:
68
69 IRQL = DISPATCH_LEVEL
70
71 ==========================================================================
72*/
73VOID PeerAuthSimpleRspGenAndSend(
74 IN PRTMP_ADAPTER pAd,
75 IN PHEADER_802_11 pHdr80211,
76 IN USHORT Alg,
77 IN USHORT Seq,
78 IN USHORT Reason,
79 IN USHORT Status)
80{
81 HEADER_802_11 AuthHdr;
82 ULONG FrameLen = 0;
83 PUCHAR pOutBuffer = NULL;
84 NDIS_STATUS NStatus;
85
86 if (Reason != MLME_SUCCESS)
87 {
88 DBGPRINT(RT_DEBUG_TRACE, ("Peer AUTH fail...\n"));
89 return;
90 }
91
92 //Get an unused nonpaged memory
93 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
94 if (NStatus != NDIS_STATUS_SUCCESS)
95 return;
96
97 DBGPRINT(RT_DEBUG_TRACE, ("Send AUTH response (seq#2)...\n"));
98 MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr80211->Addr2, pAd->MlmeAux.Bssid);
99 MakeOutgoingFrame(pOutBuffer, &FrameLen,
100 sizeof(HEADER_802_11), &AuthHdr,
101 2, &Alg,
102 2, &Seq,
103 2, &Reason,
104 END_OF_ARGS);
105 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
106 MlmeFreeMemory(pAd, pOutBuffer);
107}
108
109/*
110 ==========================================================================
111 Description:
112
113 IRQL = DISPATCH_LEVEL
114
115 ==========================================================================
116*/
117VOID PeerDeauthAction(
118 IN PRTMP_ADAPTER pAd,
119 IN PMLME_QUEUE_ELEM Elem)
120{
121 UCHAR Addr2[MAC_ADDR_LEN];
122 USHORT Reason;
123
124 if (PeerDeauthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason))
125 {
126 if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(Addr2, pAd->CommonCfg.Bssid))
127 {
128 DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - receive DE-AUTH from our AP (Reason=%d)\n", Reason));
129
130 {
131 union iwreq_data wrqu;
132 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
133 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
134 }
135
136 // send wireless event - for deauthentication
137 if (pAd->CommonCfg.bWirelessEvent)
138 RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
139
140 LinkDown(pAd, TRUE);
141 }
142 }
143 else
144 {
145 DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - PeerDeauthAction() sanity check fail\n"));
146 }
147}
148
diff --git a/drivers/staging/rt2870/sta/connect.c b/drivers/staging/rt2870/sta/connect.c
index 75ff2f153988..f6c7bbf542dc 100644
--- a/drivers/staging/rt2870/sta/connect.c
+++ b/drivers/staging/rt2870/sta/connect.c
@@ -1,2469 +1 @@
1/* #include "../../rt2860/sta/connect.c"
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 connect.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 John 2004-08-08 Major modification from RT2560
36*/
37#include "../rt_config.h"
38
39UCHAR CipherSuiteWpaNoneTkip[] = {
40 0x00, 0x50, 0xf2, 0x01, // oui
41 0x01, 0x00, // Version
42 0x00, 0x50, 0xf2, 0x02, // Multicast
43 0x01, 0x00, // Number of unicast
44 0x00, 0x50, 0xf2, 0x02, // unicast
45 0x01, 0x00, // number of authentication method
46 0x00, 0x50, 0xf2, 0x00 // authentication
47 };
48UCHAR CipherSuiteWpaNoneTkipLen = (sizeof(CipherSuiteWpaNoneTkip) / sizeof(UCHAR));
49
50UCHAR CipherSuiteWpaNoneAes[] = {
51 0x00, 0x50, 0xf2, 0x01, // oui
52 0x01, 0x00, // Version
53 0x00, 0x50, 0xf2, 0x04, // Multicast
54 0x01, 0x00, // Number of unicast
55 0x00, 0x50, 0xf2, 0x04, // unicast
56 0x01, 0x00, // number of authentication method
57 0x00, 0x50, 0xf2, 0x00 // authentication
58 };
59UCHAR CipherSuiteWpaNoneAesLen = (sizeof(CipherSuiteWpaNoneAes) / sizeof(UCHAR));
60
61// The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS,
62// or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS
63// All settings successfuly negotiated furing MLME state machines become final settings
64// and are copied to pAd->StaActive
65#define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \
66{ \
67 (_pAd)->CommonCfg.SsidLen = (_pAd)->MlmeAux.SsidLen; \
68 NdisMoveMemory((_pAd)->CommonCfg.Ssid, (_pAd)->MlmeAux.Ssid, (_pAd)->MlmeAux.SsidLen); \
69 COPY_MAC_ADDR((_pAd)->CommonCfg.Bssid, (_pAd)->MlmeAux.Bssid); \
70 (_pAd)->CommonCfg.Channel = (_pAd)->MlmeAux.Channel; \
71 (_pAd)->CommonCfg.CentralChannel = (_pAd)->MlmeAux.CentralChannel; \
72 (_pAd)->StaActive.Aid = (_pAd)->MlmeAux.Aid; \
73 (_pAd)->StaActive.AtimWin = (_pAd)->MlmeAux.AtimWin; \
74 (_pAd)->StaActive.CapabilityInfo = (_pAd)->MlmeAux.CapabilityInfo; \
75 (_pAd)->CommonCfg.BeaconPeriod = (_pAd)->MlmeAux.BeaconPeriod; \
76 (_pAd)->StaActive.CfpMaxDuration = (_pAd)->MlmeAux.CfpMaxDuration; \
77 (_pAd)->StaActive.CfpPeriod = (_pAd)->MlmeAux.CfpPeriod; \
78 (_pAd)->StaActive.SupRateLen = (_pAd)->MlmeAux.SupRateLen; \
79 NdisMoveMemory((_pAd)->StaActive.SupRate, (_pAd)->MlmeAux.SupRate, (_pAd)->MlmeAux.SupRateLen);\
80 (_pAd)->StaActive.ExtRateLen = (_pAd)->MlmeAux.ExtRateLen; \
81 NdisMoveMemory((_pAd)->StaActive.ExtRate, (_pAd)->MlmeAux.ExtRate, (_pAd)->MlmeAux.ExtRateLen);\
82 NdisMoveMemory(&(_pAd)->CommonCfg.APEdcaParm, &(_pAd)->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));\
83 NdisMoveMemory(&(_pAd)->CommonCfg.APQosCapability, &(_pAd)->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));\
84 NdisMoveMemory(&(_pAd)->CommonCfg.APQbssLoad, &(_pAd)->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));\
85 COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].Addr, (_pAd)->MlmeAux.Bssid); \
86 (_pAd)->MacTab.Content[BSSID_WCID].Aid = (_pAd)->MlmeAux.Aid; \
87 (_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = (_pAd)->StaCfg.PairCipher;\
88 COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.BssId, (_pAd)->MlmeAux.Bssid);\
89 (_pAd)->MacTab.Content[BSSID_WCID].RateLen = (_pAd)->StaActive.SupRateLen + (_pAd)->StaActive.ExtRateLen;\
90}
91
92/*
93 ==========================================================================
94 Description:
95
96 IRQL = PASSIVE_LEVEL
97
98 ==========================================================================
99*/
100VOID MlmeCntlInit(
101 IN PRTMP_ADAPTER pAd,
102 IN STATE_MACHINE *S,
103 OUT STATE_MACHINE_FUNC Trans[])
104{
105 // Control state machine differs from other state machines, the interface
106 // follows the standard interface
107 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
108}
109
110/*
111 ==========================================================================
112 Description:
113
114 IRQL = DISPATCH_LEVEL
115
116 ==========================================================================
117*/
118VOID MlmeCntlMachinePerformAction(
119 IN PRTMP_ADAPTER pAd,
120 IN STATE_MACHINE *S,
121 IN MLME_QUEUE_ELEM *Elem)
122{
123 switch(pAd->Mlme.CntlMachine.CurrState)
124 {
125 case CNTL_IDLE:
126 CntlIdleProc(pAd, Elem);
127 break;
128 case CNTL_WAIT_DISASSOC:
129 CntlWaitDisassocProc(pAd, Elem);
130 break;
131 case CNTL_WAIT_JOIN:
132 CntlWaitJoinProc(pAd, Elem);
133 break;
134
135 // CNTL_WAIT_REASSOC is the only state in CNTL machine that does
136 // not triggered directly or indirectly by "RTMPSetInformation(OID_xxx)".
137 // Therefore not protected by NDIS's "only one outstanding OID request"
138 // rule. Which means NDIS may SET OID in the middle of ROAMing attempts.
139 // Current approach is to block new SET request at RTMPSetInformation()
140 // when CntlMachine.CurrState is not CNTL_IDLE
141 case CNTL_WAIT_REASSOC:
142 CntlWaitReassocProc(pAd, Elem);
143 break;
144
145 case CNTL_WAIT_START:
146 CntlWaitStartProc(pAd, Elem);
147 break;
148 case CNTL_WAIT_AUTH:
149 CntlWaitAuthProc(pAd, Elem);
150 break;
151 case CNTL_WAIT_AUTH2:
152 CntlWaitAuthProc2(pAd, Elem);
153 break;
154 case CNTL_WAIT_ASSOC:
155 CntlWaitAssocProc(pAd, Elem);
156 break;
157
158 case CNTL_WAIT_OID_LIST_SCAN:
159 if(Elem->MsgType == MT2_SCAN_CONF)
160 {
161 // Resume TxRing after SCANING complete. We hope the out-of-service time
162 // won't be too long to let upper layer time-out the waiting frames
163 RTMPResumeMsduTransmission(pAd);
164 if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED)
165 {
166 // Cisco scan request is finished, prepare beacon report
167 MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL);
168 }
169 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
170
171 //
172 // Set LED status to previous status.
173 //
174 if (pAd->bLedOnScanning)
175 {
176 pAd->bLedOnScanning = FALSE;
177 RTMPSetLED(pAd, pAd->LedStatus);
178 }
179 }
180 break;
181
182 case CNTL_WAIT_OID_DISASSOC:
183 if (Elem->MsgType == MT2_DISASSOC_CONF)
184 {
185 LinkDown(pAd, FALSE);
186 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
187 }
188 break;
189#ifdef RT2870
190 //
191 // This state is for that we want to connect to an AP but
192 // it didn't find on BSS List table. So we need to scan the air first,
193 // after that we can try to connect to the desired AP if available.
194 //
195 case CNTL_WAIT_SCAN_FOR_CONNECT:
196 if(Elem->MsgType == MT2_SCAN_CONF)
197 {
198 // Resume TxRing after SCANING complete. We hope the out-of-service time
199 // won't be too long to let upper layer time-out the waiting frames
200 RTMPResumeMsduTransmission(pAd);
201#ifdef CCX_SUPPORT
202 if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED)
203 {
204 // Cisco scan request is finished, prepare beacon report
205 MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL);
206 }
207#endif // CCX_SUPPORT //
208 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
209
210 //
211 // Check if we can connect to.
212 //
213 BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
214 if (pAd->MlmeAux.SsidBssTab.BssNr > 0)
215 {
216 MlmeAutoReconnectLastSSID(pAd);
217 }
218 }
219 break;
220#endif // RT2870 //
221 default:
222 DBGPRINT_ERR(("!ERROR! CNTL - Illegal message type(=%ld)", Elem->MsgType));
223 break;
224 }
225}
226
227
228/*
229 ==========================================================================
230 Description:
231
232 IRQL = DISPATCH_LEVEL
233
234 ==========================================================================
235*/
236VOID CntlIdleProc(
237 IN PRTMP_ADAPTER pAd,
238 IN MLME_QUEUE_ELEM *Elem)
239{
240 MLME_DISASSOC_REQ_STRUCT DisassocReq;
241
242 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
243 return;
244
245 switch(Elem->MsgType)
246 {
247 case OID_802_11_SSID:
248 CntlOidSsidProc(pAd, Elem);
249 break;
250
251 case OID_802_11_BSSID:
252 CntlOidRTBssidProc(pAd,Elem);
253 break;
254
255 case OID_802_11_BSSID_LIST_SCAN:
256 CntlOidScanProc(pAd,Elem);
257 break;
258
259 case OID_802_11_DISASSOCIATE:
260 DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
261 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
262 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
263
264 if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE_WITH_WEB_UI)
265 {
266 // Set the AutoReconnectSsid to prevent it reconnect to old SSID
267 // Since calling this indicate user don't want to connect to that SSID anymore.
268 pAd->MlmeAux.AutoReconnectSsidLen= 32;
269 NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
270 }
271 break;
272
273 case MT2_MLME_ROAMING_REQ:
274 CntlMlmeRoamingProc(pAd, Elem);
275 break;
276
277 case OID_802_11_MIC_FAILURE_REPORT_FRAME:
278 WpaMicFailureReportFrame(pAd, Elem);
279 break;
280
281 default:
282 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Illegal message in CntlIdleProc(MsgType=%ld)\n",Elem->MsgType));
283 break;
284 }
285}
286
287VOID CntlOidScanProc(
288 IN PRTMP_ADAPTER pAd,
289 IN MLME_QUEUE_ELEM *Elem)
290{
291 MLME_SCAN_REQ_STRUCT ScanReq;
292 ULONG BssIdx = BSS_NOT_FOUND;
293 BSS_ENTRY CurrBss;
294
295 // record current BSS if network is connected.
296 // 2003-2-13 do not include current IBSS if this is the only STA in this IBSS.
297 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
298 {
299 BssIdx = BssSsidTableSearch(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Channel);
300 if (BssIdx != BSS_NOT_FOUND)
301 {
302 NdisMoveMemory(&CurrBss, &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY));
303 }
304 }
305
306 // clean up previous SCAN result, add current BSS back to table if any
307 BssTableInit(&pAd->ScanTab);
308 if (BssIdx != BSS_NOT_FOUND)
309 {
310 // DDK Note: If the NIC is associated with a particular BSSID and SSID
311 // that are not contained in the list of BSSIDs generated by this scan, the
312 // BSSID description of the currently associated BSSID and SSID should be
313 // appended to the list of BSSIDs in the NIC's database.
314 // To ensure this, we append this BSS as the first entry in SCAN result
315 NdisMoveMemory(&pAd->ScanTab.BssEntry[0], &CurrBss, sizeof(BSS_ENTRY));
316 pAd->ScanTab.BssNr = 1;
317 }
318
319 ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_ACTIVE);
320 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ,
321 sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
322 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
323}
324
325/*
326 ==========================================================================
327 Description:
328 Before calling this routine, user desired SSID should already been
329 recorded in CommonCfg.Ssid[]
330 IRQL = DISPATCH_LEVEL
331
332 ==========================================================================
333*/
334VOID CntlOidSsidProc(
335 IN PRTMP_ADAPTER pAd,
336 IN MLME_QUEUE_ELEM * Elem)
337{
338 PNDIS_802_11_SSID pOidSsid = (NDIS_802_11_SSID *)Elem->Msg;
339 MLME_DISASSOC_REQ_STRUCT DisassocReq;
340 ULONG Now;
341
342 // Step 1. record the desired user settings to MlmeAux
343 NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
344 NdisMoveMemory(pAd->MlmeAux.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength);
345 pAd->MlmeAux.SsidLen = (UCHAR)pOidSsid->SsidLength;
346 NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
347 pAd->MlmeAux.BssType = pAd->StaCfg.BssType;
348
349
350 //
351 // Update Reconnect Ssid, that user desired to connect.
352 //
353 NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID);
354 NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
355 pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen;
356
357 // step 2. find all matching BSS in the lastest SCAN result (inBssTab)
358 // & log them into MlmeAux.SsidBssTab for later-on iteration. Sort by RSSI order
359 BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
360
361 DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - %d BSS of %d BSS match the desire (%d)SSID - %s\n",
362 pAd->MlmeAux.SsidBssTab.BssNr, pAd->ScanTab.BssNr, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid));
363 NdisGetSystemUpTime(&Now);
364
365 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
366 (pAd->CommonCfg.SsidLen == pAd->MlmeAux.SsidBssTab.BssEntry[0].SsidLen) &&
367 NdisEqualMemory(pAd->CommonCfg.Ssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Ssid, pAd->CommonCfg.SsidLen) &&
368 MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid))
369 {
370 // Case 1. already connected with an AP who has the desired SSID
371 // with highest RSSI
372
373 // Add checking Mode "LEAP" for CCX 1.0
374 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
375 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
376 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
377 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
378 ) &&
379 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
380 {
381 // case 1.1 For WPA, WPA-PSK, if the 1x port is not secured, we have to redo
382 // connection process
383 DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n"));
384 DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
385 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
386 sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
387 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
388 }
389 else if (pAd->bConfigChanged == TRUE)
390 {
391 // case 1.2 Important Config has changed, we have to reconnect to the same AP
392 DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP Because config changed...\n"));
393 DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
394 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
395 sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
396 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
397 }
398 else
399 {
400 // case 1.3. already connected to the SSID with highest RSSI.
401 DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - already with this BSSID. ignore this SET_SSID request\n"));
402 //
403 // (HCT 12.1) 1c_wlan_mediaevents required
404 // media connect events are indicated when associating with the same AP
405 //
406 if (INFRA_ON(pAd))
407 {
408 //
409 // Since MediaState already is NdisMediaStateConnected
410 // We just indicate the connect event again to meet the WHQL required.
411 //
412 pAd->IndicateMediaState = NdisMediaStateConnected;
413 RTMP_IndicateMediaState(pAd);
414 pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up
415 }
416
417 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
418
419 {
420 union iwreq_data wrqu;
421
422 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
423 memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
424 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
425
426 }
427 }
428 }
429 else if (INFRA_ON(pAd))
430 {
431 //
432 // For RT61
433 // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: )
434 // RT61 may lost SSID, and not connect to NDTEST_WEP_AP2 and will connect to NDTEST_WEP_AP2 by Autoreconnect
435 // But media status is connected, so the SSID not report correctly.
436 //
437 if (!SSID_EQUAL(pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen))
438 {
439 //
440 // Different SSID means not Roaming case, so we let LinkDown() to Indicate a disconnect event.
441 //
442 pAd->MlmeAux.CurrReqIsFromNdis = TRUE;
443 }
444 // case 2. active INFRA association existent
445 // roaming is done within miniport driver, nothing to do with configuration
446 // utility. so upon a new SET(OID_802_11_SSID) is received, we just
447 // disassociate with the current associated AP,
448 // then perform a new association with this new SSID, no matter the
449 // new/old SSID are the same or not.
450 DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n"));
451 DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
452 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
453 sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
454 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
455 }
456 else
457 {
458 if (ADHOC_ON(pAd))
459 {
460 DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - drop current ADHOC\n"));
461 LinkDown(pAd, FALSE);
462 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
463 pAd->IndicateMediaState = NdisMediaStateDisconnected;
464 RTMP_IndicateMediaState(pAd);
465 pAd->ExtraInfo = GENERAL_LINK_DOWN;
466 DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():NDIS_STATUS_MEDIA_DISCONNECT Event C!\n"));
467 }
468
469 if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) &&
470 (pAd->StaCfg.bAutoReconnect == TRUE) &&
471 (pAd->MlmeAux.BssType == BSS_INFRA) &&
472 (MlmeValidateSSID(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen) == TRUE)
473 )
474 {
475 MLME_SCAN_REQ_STRUCT ScanReq;
476
477 DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - No matching BSS, start a new scan\n"));
478 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE);
479 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
480 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
481 // Reset Missed scan number
482 pAd->StaCfg.LastScanTime = Now;
483 }
484 else
485 {
486 pAd->MlmeAux.BssIdx = 0;
487 IterateOnBssTab(pAd);
488 }
489 }
490}
491
492
493/*
494 ==========================================================================
495 Description:
496
497 IRQL = DISPATCH_LEVEL
498
499 ==========================================================================
500*/
501VOID CntlOidRTBssidProc(
502 IN PRTMP_ADAPTER pAd,
503 IN MLME_QUEUE_ELEM * Elem)
504{
505 ULONG BssIdx;
506 PUCHAR pOidBssid = (PUCHAR)Elem->Msg;
507 MLME_DISASSOC_REQ_STRUCT DisassocReq;
508 MLME_JOIN_REQ_STRUCT JoinReq;
509
510 // record user desired settings
511 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pOidBssid);
512 pAd->MlmeAux.BssType = pAd->StaCfg.BssType;
513
514 //
515 // Update Reconnect Ssid, that user desired to connect.
516 //
517 NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID);
518 pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen;
519 NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
520
521 // find the desired BSS in the latest SCAN result table
522 BssIdx = BssTableSearch(&pAd->ScanTab, pOidBssid, pAd->MlmeAux.Channel);
523 if (BssIdx == BSS_NOT_FOUND)
524 {
525 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n"));
526 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
527 return;
528 }
529
530 // copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. Why?
531 // Because we need this entry to become the JOIN target in later on SYNC state machine
532 pAd->MlmeAux.BssIdx = 0;
533 pAd->MlmeAux.SsidBssTab.BssNr = 1;
534 NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0], &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY));
535
536 // 2002-11-26 skip the following checking. i.e. if user wants to re-connect to same AP
537 // we just follow normal procedure. The reason of user doing this may because he/she changed
538 // AP to another channel, but we still received BEACON from it thus don't claim Link Down.
539 // Since user knows he's changed AP channel, he'll re-connect again. By skipping the following
540 // checking, we'll disassociate then re-do normal association with this AP at the new channel.
541 // 2003-1-6 Re-enable this feature based on microsoft requirement which prefer not to re-do
542 // connection when setting the same BSSID.
543 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
544 MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pOidBssid))
545 {
546 // already connected to the same BSSID, go back to idle state directly
547 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - already in this BSSID. ignore this SET_BSSID request\n"));
548 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
549
550 {
551 union iwreq_data wrqu;
552
553 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
554 memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
555 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
556
557 }
558 }
559 else
560 {
561 if (INFRA_ON(pAd))
562 {
563 // disassoc from current AP first
564 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - disassociate with current AP ...\n"));
565 DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
566 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
567 sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
568
569 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
570 }
571 else
572 {
573 if (ADHOC_ON(pAd))
574 {
575 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - drop current ADHOC\n"));
576 LinkDown(pAd, FALSE);
577 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
578 pAd->IndicateMediaState = NdisMediaStateDisconnected;
579 RTMP_IndicateMediaState(pAd);
580 pAd->ExtraInfo = GENERAL_LINK_DOWN;
581 DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event C!\n"));
582 }
583
584 // Change the wepstatus to original wepstatus
585 pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus;
586 pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus;
587 pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus;
588
589 // Check cipher suite, AP must have more secured cipher than station setting
590 // Set the Pairwise and Group cipher to match the intended AP setting
591 // We can only connect to AP with less secured cipher setting
592 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
593 {
594 pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.GroupCipher;
595
596 if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher)
597 pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher;
598 else if (pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled)
599 pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux;
600 else // There is no PairCipher Aux, downgrade our capability to TKIP
601 pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
602 }
603 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
604 {
605 pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.GroupCipher;
606
607 if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher)
608 pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher;
609 else if (pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled)
610 pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux;
611 else // There is no PairCipher Aux, downgrade our capability to TKIP
612 pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
613
614 // RSN capability
615 pAd->StaCfg.RsnCapability = pAd->ScanTab.BssEntry[BssIdx].WPA2.RsnCapability;
616 }
617
618 // Set Mix cipher flag
619 pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE;
620 if (pAd->StaCfg.bMixCipher == TRUE)
621 {
622 // If mix cipher, re-build RSNIE
623 RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0);
624 }
625 // No active association, join the BSS immediately
626 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - joining %02x:%02x:%02x:%02x:%02x:%02x ...\n",
627 pOidBssid[0],pOidBssid[1],pOidBssid[2],pOidBssid[3],pOidBssid[4],pOidBssid[5]));
628
629 JoinParmFill(pAd, &JoinReq, pAd->MlmeAux.BssIdx);
630 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), &JoinReq);
631
632 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN;
633 }
634 }
635}
636
637// Roaming is the only external request triggering CNTL state machine
638// despite of other "SET OID" operation. All "SET OID" related oerations
639// happen in sequence, because no other SET OID will be sent to this device
640// until the the previous SET operation is complete (successful o failed).
641// So, how do we quarantee this ROAMING request won't corrupt other "SET OID"?
642// or been corrupted by other "SET OID"?
643//
644// IRQL = DISPATCH_LEVEL
645VOID CntlMlmeRoamingProc(
646 IN PRTMP_ADAPTER pAd,
647 IN MLME_QUEUE_ELEM *Elem)
648{
649 // TODO:
650 // AP in different channel may show lower RSSI than actual value??
651 // should we add a weighting factor to compensate it?
652 DBGPRINT(RT_DEBUG_TRACE,("CNTL - Roaming in MlmeAux.RoamTab...\n"));
653
654 NdisMoveMemory(&pAd->MlmeAux.SsidBssTab, &pAd->MlmeAux.RoamTab, sizeof(pAd->MlmeAux.RoamTab));
655 pAd->MlmeAux.SsidBssTab.BssNr = pAd->MlmeAux.RoamTab.BssNr;
656
657 BssTableSortByRssi(&pAd->MlmeAux.SsidBssTab);
658 pAd->MlmeAux.BssIdx = 0;
659 IterateOnBssTab(pAd);
660}
661
662/*
663 ==========================================================================
664 Description:
665
666 IRQL = DISPATCH_LEVEL
667
668 ==========================================================================
669*/
670VOID CntlWaitDisassocProc(
671 IN PRTMP_ADAPTER pAd,
672 IN MLME_QUEUE_ELEM *Elem)
673{
674 MLME_START_REQ_STRUCT StartReq;
675
676 if (Elem->MsgType == MT2_DISASSOC_CONF)
677 {
678 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Dis-associate successful\n"));
679
680 if (pAd->CommonCfg.bWirelessEvent)
681 {
682 RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
683 }
684
685 LinkDown(pAd, FALSE);
686
687 // case 1. no matching BSS, and user wants ADHOC, so we just start a new one
688 if ((pAd->MlmeAux.SsidBssTab.BssNr==0) && (pAd->StaCfg.BssType == BSS_ADHOC))
689 {
690 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - No matching BSS, start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid));
691 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
692 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
693 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
694 }
695 // case 2. try each matched BSS
696 else
697 {
698 pAd->MlmeAux.BssIdx = 0;
699
700 IterateOnBssTab(pAd);
701 }
702 }
703}
704
705/*
706 ==========================================================================
707 Description:
708
709 IRQL = DISPATCH_LEVEL
710
711 ==========================================================================
712*/
713VOID CntlWaitJoinProc(
714 IN PRTMP_ADAPTER pAd,
715 IN MLME_QUEUE_ELEM *Elem)
716{
717 USHORT Reason;
718 MLME_AUTH_REQ_STRUCT AuthReq;
719
720 if (Elem->MsgType == MT2_JOIN_CONF)
721 {
722 NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
723 if (Reason == MLME_SUCCESS)
724 {
725 // 1. joined an IBSS, we are pretty much done here
726 if (pAd->MlmeAux.BssType == BSS_ADHOC)
727 {
728 //
729 // 5G bands rules of Japan:
730 // Ad hoc must be disabled in W53(ch52,56,60,64) channels.
731 //
732 if ( (pAd->CommonCfg.bIEEE80211H == 1) &&
733 RadarChannelCheck(pAd, pAd->CommonCfg.Channel)
734 )
735 {
736 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
737 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Join adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel));
738 return;
739 }
740
741 LinkUp(pAd, BSS_ADHOC);
742 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
743 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - join the IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n",
744 pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2],
745 pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5]));
746
747 pAd->IndicateMediaState = NdisMediaStateConnected;
748 pAd->ExtraInfo = GENERAL_LINK_UP;
749 }
750 // 2. joined a new INFRA network, start from authentication
751 else
752 {
753 {
754 // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first
755 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) ||
756 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch))
757 {
758 AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared);
759 }
760 else
761 {
762 AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen);
763 }
764 }
765 MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ,
766 sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq);
767
768 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH;
769 }
770 }
771 else
772 {
773 // 3. failed, try next BSS
774 pAd->MlmeAux.BssIdx++;
775 IterateOnBssTab(pAd);
776 }
777 }
778}
779
780
781/*
782 ==========================================================================
783 Description:
784
785 IRQL = DISPATCH_LEVEL
786
787 ==========================================================================
788*/
789VOID CntlWaitStartProc(
790 IN PRTMP_ADAPTER pAd,
791 IN MLME_QUEUE_ELEM *Elem)
792{
793 USHORT Result;
794
795 if (Elem->MsgType == MT2_START_CONF)
796 {
797 NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT));
798 if (Result == MLME_SUCCESS)
799 {
800 //
801 // 5G bands rules of Japan:
802 // Ad hoc must be disabled in W53(ch52,56,60,64) channels.
803 //
804 if ( (pAd->CommonCfg.bIEEE80211H == 1) &&
805 RadarChannelCheck(pAd, pAd->CommonCfg.Channel)
806 )
807 {
808 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
809 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Start adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel));
810 return;
811 }
812
813 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
814 {
815 N_ChannelCheck(pAd);
816 SetCommonHT(pAd);
817 NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &pAd->CommonCfg.AddHTInfo, sizeof(ADD_HT_INFO_IE));
818 RTMPCheckHt(pAd, BSSID_WCID, &pAd->CommonCfg.HtCapability, &pAd->CommonCfg.AddHTInfo);
819 pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
820 NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], 16);
821 NdisMoveMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], &pAd->CommonCfg.HtCapability.MCSSet[0], 16);
822 COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
823
824 if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
825 (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE))
826 {
827 pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel + 2;
828 }
829 else if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
830 (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW))
831 {
832 pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel - 2;
833 }
834 }
835 else
836 {
837 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
838 }
839 LinkUp(pAd, BSS_ADHOC);
840 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
841 // Before send beacon, driver need do radar detection
842 if ((pAd->CommonCfg.Channel > 14 )
843 && (pAd->CommonCfg.bIEEE80211H == 1)
844 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
845 {
846 pAd->CommonCfg.RadarDetect.RDMode = RD_SILENCE_MODE;
847 pAd->CommonCfg.RadarDetect.RDCount = 0;
848 }
849
850 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - start a new IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n",
851 pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2],
852 pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5]));
853 }
854 else
855 {
856 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Start IBSS fail. BUG!!!!!\n"));
857 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
858 }
859 }
860}
861
862/*
863 ==========================================================================
864 Description:
865
866 IRQL = DISPATCH_LEVEL
867
868 ==========================================================================
869*/
870VOID CntlWaitAuthProc(
871 IN PRTMP_ADAPTER pAd,
872 IN MLME_QUEUE_ELEM *Elem)
873{
874 USHORT Reason;
875 MLME_ASSOC_REQ_STRUCT AssocReq;
876 MLME_AUTH_REQ_STRUCT AuthReq;
877
878 if (Elem->MsgType == MT2_AUTH_CONF)
879 {
880 NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
881 if (Reason == MLME_SUCCESS)
882 {
883 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n"));
884 AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo,
885 ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount);
886
887 {
888 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ,
889 sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq);
890
891 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC;
892 }
893 }
894 else
895 {
896 // This fail may because of the AP already keep us in its MAC table without
897 // ageing-out. The previous authentication attempt must have let it remove us.
898 // so try Authentication again may help. For D-Link DWL-900AP+ compatibility.
899 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try again...\n"));
900
901 {
902 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) ||
903 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch))
904 {
905 // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first
906 AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared);
907 }
908 else
909 {
910 AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen);
911 }
912 }
913 MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ,
914 sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq);
915
916 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2;
917 }
918 }
919}
920
921/*
922 ==========================================================================
923 Description:
924
925 IRQL = DISPATCH_LEVEL
926
927 ==========================================================================
928*/
929VOID CntlWaitAuthProc2(
930 IN PRTMP_ADAPTER pAd,
931 IN MLME_QUEUE_ELEM *Elem)
932{
933 USHORT Reason;
934 MLME_ASSOC_REQ_STRUCT AssocReq;
935 MLME_AUTH_REQ_STRUCT AuthReq;
936
937 if (Elem->MsgType == MT2_AUTH_CONF)
938 {
939 NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
940 if (Reason == MLME_SUCCESS)
941 {
942 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n"));
943 AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo,
944 ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount);
945 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ,
946 sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq);
947
948 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC;
949 }
950 else
951 {
952 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch) &&
953 (pAd->MlmeAux.Alg == Ndis802_11AuthModeShared))
954 {
955 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try OPEN system...\n"));
956 AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen);
957 MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ,
958 sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq);
959
960 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2;
961 }
962 else
963 {
964 // not success, try next BSS
965 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, give up; try next BSS\n"));
966 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; //???????
967 pAd->MlmeAux.BssIdx++;
968 IterateOnBssTab(pAd);
969 }
970 }
971 }
972}
973
974/*
975 ==========================================================================
976 Description:
977
978 IRQL = DISPATCH_LEVEL
979
980 ==========================================================================
981*/
982VOID CntlWaitAssocProc(
983 IN PRTMP_ADAPTER pAd,
984 IN MLME_QUEUE_ELEM *Elem)
985{
986 USHORT Reason;
987
988 if (Elem->MsgType == MT2_ASSOC_CONF)
989 {
990 NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
991 if (Reason == MLME_SUCCESS)
992 {
993 LinkUp(pAd, BSS_INFRA);
994 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
995 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association successful on BSS #%ld\n",pAd->MlmeAux.BssIdx));
996
997 if (pAd->CommonCfg.bWirelessEvent)
998 {
999 RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1000 }
1001 }
1002 else
1003 {
1004 // not success, try next BSS
1005 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association fails on BSS #%ld\n",pAd->MlmeAux.BssIdx));
1006 pAd->MlmeAux.BssIdx++;
1007 IterateOnBssTab(pAd);
1008 }
1009 }
1010}
1011
1012/*
1013 ==========================================================================
1014 Description:
1015
1016 IRQL = DISPATCH_LEVEL
1017
1018 ==========================================================================
1019*/
1020VOID CntlWaitReassocProc(
1021 IN PRTMP_ADAPTER pAd,
1022 IN MLME_QUEUE_ELEM *Elem)
1023{
1024 USHORT Result;
1025
1026 if (Elem->MsgType == MT2_REASSOC_CONF)
1027 {
1028 NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT));
1029 if (Result == MLME_SUCCESS)
1030 {
1031 //
1032 // NDIS requires a new Link UP indication but no Link Down for RE-ASSOC
1033 //
1034 LinkUp(pAd, BSS_INFRA);
1035
1036 // send wireless event - for association
1037 if (pAd->CommonCfg.bWirelessEvent)
1038 RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1039
1040 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
1041 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition successful on BSS #%ld\n", pAd->MlmeAux.RoamIdx));
1042 }
1043 else
1044 {
1045 // reassoc failed, try to pick next BSS in the BSS Table
1046 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition fails on BSS #%ld\n", pAd->MlmeAux.RoamIdx));
1047 pAd->MlmeAux.RoamIdx++;
1048 IterateOnBssTab2(pAd);
1049 }
1050 }
1051}
1052
1053
1054VOID AdhocTurnOnQos(
1055 IN PRTMP_ADAPTER pAd)
1056{
1057#define AC0_DEF_TXOP 0
1058#define AC1_DEF_TXOP 0
1059#define AC2_DEF_TXOP 94
1060#define AC3_DEF_TXOP 47
1061
1062 // Turn on QOs if use HT rate.
1063 if (pAd->CommonCfg.APEdcaParm.bValid == FALSE)
1064 {
1065 pAd->CommonCfg.APEdcaParm.bValid = TRUE;
1066 pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3;
1067 pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7;
1068 pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1;
1069 pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1;
1070
1071 pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4;
1072 pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4;
1073 pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3;
1074 pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2;
1075
1076 pAd->CommonCfg.APEdcaParm.Cwmax[0] = 10;
1077 pAd->CommonCfg.APEdcaParm.Cwmax[1] = 6;
1078 pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4;
1079 pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3;
1080
1081 pAd->CommonCfg.APEdcaParm.Txop[0] = 0;
1082 pAd->CommonCfg.APEdcaParm.Txop[1] = 0;
1083 pAd->CommonCfg.APEdcaParm.Txop[2] = AC2_DEF_TXOP;
1084 pAd->CommonCfg.APEdcaParm.Txop[3] = AC3_DEF_TXOP;
1085 }
1086 AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
1087}
1088
1089/*
1090 ==========================================================================
1091 Description:
1092
1093 IRQL = DISPATCH_LEVEL
1094
1095 ==========================================================================
1096*/
1097VOID LinkUp(
1098 IN PRTMP_ADAPTER pAd,
1099 IN UCHAR BssType)
1100{
1101 ULONG Now;
1102 UINT32 Data;
1103 BOOLEAN Cancelled;
1104 UCHAR Value = 0, idx;
1105 MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
1106
1107 pEntry = &pAd->MacTab.Content[BSSID_WCID];
1108
1109 //
1110 // ASSOC - DisassocTimeoutAction
1111 // CNTL - Dis-associate successful
1112 // !!! LINK DOWN !!!
1113 // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: )
1114 //
1115 // To prevent DisassocTimeoutAction to call Link down after we link up,
1116 // cancel the DisassocTimer no matter what it start or not.
1117 //
1118 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
1119
1120 COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
1121
1122 COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
1123
1124 // It's quite difficult to tell if a newly added KEY is WEP or CKIP until a new BSS
1125 // is formed (either ASSOC/RE-ASSOC done or IBSS started. LinkUP should be a safe place
1126 // to examine if cipher algorithm switching is required.
1127 //rt2860b. Don't know why need this
1128 SwitchBetweenWepAndCkip(pAd);
1129
1130
1131 if (BssType == BSS_ADHOC)
1132 {
1133 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_ADHOC_ON);
1134 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
1135
1136#ifdef RT30xx
1137 if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
1138 (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE))
1139 {
1140 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2;
1141 }
1142 else if ((pAd->CommonCfg.Channel > 2) &&
1143 (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
1144 (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW))
1145 {
1146 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2;
1147 }
1148#endif
1149
1150 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1151 AdhocTurnOnQos(pAd);
1152
1153 DBGPRINT(RT_DEBUG_TRACE, ("!!!Adhoc LINK UP !!! \n" ));
1154 }
1155 else
1156 {
1157 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_INFRA_ON);
1158 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
1159
1160 DBGPRINT(RT_DEBUG_TRACE, ("!!!Infra LINK UP !!! \n" ));
1161 }
1162
1163 // 3*3
1164 // reset Tx beamforming bit
1165 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
1166 Value &= (~0x01);
1167 Value |= pAd->CommonCfg.RegTransmitSetting.field.TxBF;
1168 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
1169
1170 // Change to AP channel
1171 if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1172 {
1173 // Must using 40MHz.
1174 pAd->CommonCfg.BBPCurrentBW = BW_40;
1175 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1176 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1177
1178 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
1179 Value &= (~0x18);
1180 Value |= 0x10;
1181 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
1182
1183 // RX : control channel at lower
1184 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
1185 Value &= (~0x20);
1186 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
1187
1188 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
1189 Data &= 0xfffffffe;
1190 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
1191
1192 if (pAd->MACVersion == 0x28600100)
1193 {
1194 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A);
1195 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
1196 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16);
1197 DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
1198 }
1199
1200 DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel ));
1201 }
1202 else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
1203 {
1204 // Must using 40MHz.
1205 pAd->CommonCfg.BBPCurrentBW = BW_40;
1206 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
1207 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
1208
1209 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
1210 Value &= (~0x18);
1211 Value |= 0x10;
1212 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
1213
1214 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
1215 Data |= 0x1;
1216 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
1217
1218 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
1219 Value |= (0x20);
1220 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
1221
1222 if (pAd->MACVersion == 0x28600100)
1223 {
1224 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A);
1225 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
1226 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16);
1227 DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
1228 }
1229
1230 DBGPRINT(RT_DEBUG_TRACE, ("!!! 40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel ));
1231 }
1232 else
1233 {
1234 pAd->CommonCfg.BBPCurrentBW = BW_20;
1235 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
1236 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1237 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1238
1239 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
1240 Value &= (~0x18);
1241 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
1242
1243 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
1244 Data &= 0xfffffffe;
1245 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
1246
1247 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
1248 Value &= (~0x20);
1249 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
1250
1251 if (pAd->MACVersion == 0x28600100)
1252 {
1253 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
1254 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08);
1255 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11);
1256 DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
1257 }
1258
1259 DBGPRINT(RT_DEBUG_TRACE, ("!!! 20MHz LINK UP !!! \n" ));
1260 }
1261
1262 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
1263 //
1264 // Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission
1265 //
1266 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
1267
1268 DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (BssType=%d, AID=%d, ssid=%s, Channel=%d, CentralChannel = %d)\n",
1269 BssType, pAd->StaActive.Aid, pAd->CommonCfg.Ssid, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel));
1270
1271 DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (Density =%d, )\n", pAd->MacTab.Content[BSSID_WCID].MpduDensity));
1272
1273 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1274
1275 AsicSetSlotTime(pAd, TRUE);
1276 AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
1277
1278 // Call this for RTS protectionfor legacy rate, we will always enable RTS threshold, but normally it will not hit
1279 AsicUpdateProtect(pAd, 0, (OFDMSETPROTECT | CCKSETPROTECT), TRUE, FALSE);
1280
1281 if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
1282 {
1283 // Update HT protectionfor based on AP's operating mode.
1284 if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)
1285 {
1286 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE);
1287 }
1288 else
1289 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1290 }
1291
1292 NdisZeroMemory(&pAd->DrsCounters, sizeof(COUNTER_DRS));
1293
1294 NdisGetSystemUpTime(&Now);
1295 pAd->StaCfg.LastBeaconRxTime = Now; // last RX timestamp
1296
1297 if ((pAd->CommonCfg.TxPreamble != Rt802_11PreambleLong) &&
1298 CAP_IS_SHORT_PREAMBLE_ON(pAd->StaActive.CapabilityInfo))
1299 {
1300 MlmeSetTxPreamble(pAd, Rt802_11PreambleShort);
1301 }
1302
1303 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
1304
1305 if (pAd->CommonCfg.RadarDetect.RDMode == RD_SILENCE_MODE)
1306 {
1307 }
1308 pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
1309
1310 if (BssType == BSS_ADHOC)
1311 {
1312 MakeIbssBeacon(pAd);
1313 if ((pAd->CommonCfg.Channel > 14)
1314 && (pAd->CommonCfg.bIEEE80211H == 1)
1315 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1316 {
1317 ; //Do nothing
1318 }
1319 else
1320 {
1321 AsicEnableIbssSync(pAd);
1322 }
1323
1324 // In ad hoc mode, use MAC table from index 1.
1325 // p.s ASIC use all 0xff as termination of WCID table search.To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here.
1326 RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00);
1327 RTMP_IO_WRITE32(pAd, 0x1808, 0x00);
1328
1329 // If WEP is enabled, add key material and cipherAlg into Asic
1330 // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000)
1331
1332 if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)
1333 {
1334 PUCHAR Key;
1335 UCHAR CipherAlg;
1336
1337 for (idx=0; idx < SHARE_KEY_NUM; idx++)
1338 {
1339 CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg;
1340 Key = pAd->SharedKey[BSS0][idx].Key;
1341
1342 if (pAd->SharedKey[BSS0][idx].KeyLen > 0)
1343 {
1344 // Set key material and cipherAlg to Asic
1345 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
1346
1347 if (idx == pAd->StaCfg.DefaultKeyId)
1348 {
1349 // Update WCID attribute table and IVEIV table for this group key table
1350 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
1351 }
1352 }
1353
1354
1355 }
1356 }
1357 // If WPANone is enabled, add key material and cipherAlg into Asic
1358 // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000)
1359 else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
1360 {
1361 pAd->StaCfg.DefaultKeyId = 0; // always be zero
1362
1363 NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
1364 pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
1365 NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TKIP_EK);
1366
1367 if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
1368 {
1369 NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_RXMICK);
1370 NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_TXMICK);
1371 }
1372
1373 // Decide its ChiperAlg
1374 if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
1375 pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
1376 else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
1377 pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
1378 else
1379 {
1380 DBGPRINT(RT_DEBUG_TRACE, ("Unknow Cipher (=%d), set Cipher to AES\n", pAd->StaCfg.PairCipher));
1381 pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
1382 }
1383
1384 // Set key material and cipherAlg to Asic
1385 AsicAddSharedKeyEntry(pAd,
1386 BSS0,
1387 0,
1388 pAd->SharedKey[BSS0][0].CipherAlg,
1389 pAd->SharedKey[BSS0][0].Key,
1390 pAd->SharedKey[BSS0][0].TxMic,
1391 pAd->SharedKey[BSS0][0].RxMic);
1392
1393 // Update WCID attribute table and IVEIV table for this group key table
1394 RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pAd->SharedKey[BSS0][0].CipherAlg, NULL);
1395
1396 }
1397
1398 }
1399 else // BSS_INFRA
1400 {
1401 // Check the new SSID with last SSID
1402 while (Cancelled == TRUE)
1403 {
1404 if (pAd->CommonCfg.LastSsidLen == pAd->CommonCfg.SsidLen)
1405 {
1406 if (RTMPCompareMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen) == 0)
1407 {
1408 // Link to the old one no linkdown is required.
1409 break;
1410 }
1411 }
1412 // Send link down event before set to link up
1413 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1414 RTMP_IndicateMediaState(pAd);
1415 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1416 DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event AA!\n"));
1417 break;
1418 }
1419
1420 //
1421 // On WPA mode, Remove All Keys if not connect to the last BSSID
1422 // Key will be set after 4-way handshake.
1423 //
1424 if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA))
1425 {
1426 ULONG IV;
1427
1428 // Remove all WPA keys
1429 RTMPWPARemoveAllKeys(pAd);
1430 pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1431 pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
1432
1433 // Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP
1434 // If IV related values are too large in GroupMsg2, AP would ignore this message.
1435 IV = 0;
1436 IV |= (pAd->StaCfg.DefaultKeyId << 30);
1437 AsicUpdateWCIDIVEIV(pAd, BSSID_WCID, IV, 0);
1438 }
1439 // NOTE:
1440 // the decision of using "short slot time" or not may change dynamically due to
1441 // new STA association to the AP. so we have to decide that upon parsing BEACON, not here
1442
1443 // NOTE:
1444 // the decision to use "RTC/CTS" or "CTS-to-self" protection or not may change dynamically
1445 // due to new STA association to the AP. so we have to decide that upon parsing BEACON, not here
1446
1447 ComposePsPoll(pAd);
1448 ComposeNullFrame(pAd);
1449
1450 AsicEnableBssSync(pAd);
1451
1452 // Add BSSID to WCID search table
1453 AsicUpdateRxWCIDTable(pAd, BSSID_WCID, pAd->CommonCfg.Bssid);
1454
1455 NdisAcquireSpinLock(&pAd->MacTabLock);
1456 // add this BSSID entry into HASH table
1457 {
1458 UCHAR HashIdx;
1459
1460 //pEntry = &pAd->MacTab.Content[BSSID_WCID];
1461 HashIdx = MAC_ADDR_HASH_INDEX(pAd->CommonCfg.Bssid);
1462 if (pAd->MacTab.Hash[HashIdx] == NULL)
1463 {
1464 pAd->MacTab.Hash[HashIdx] = pEntry;
1465 }
1466 else
1467 {
1468 pCurrEntry = pAd->MacTab.Hash[HashIdx];
1469 while (pCurrEntry->pNext != NULL)
1470 pCurrEntry = pCurrEntry->pNext;
1471 pCurrEntry->pNext = pEntry;
1472 }
1473 }
1474 NdisReleaseSpinLock(&pAd->MacTabLock);
1475
1476
1477 // If WEP is enabled, add paiewise and shared key
1478 if (((pAd->StaCfg.WpaSupplicantUP)&&
1479 (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)&&
1480 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) ||
1481 ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)&&
1482 (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)))
1483 {
1484 PUCHAR Key;
1485 UCHAR CipherAlg;
1486
1487 for (idx=0; idx < SHARE_KEY_NUM; idx++)
1488 {
1489 CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg;
1490 Key = pAd->SharedKey[BSS0][idx].Key;
1491
1492 if (pAd->SharedKey[BSS0][idx].KeyLen > 0)
1493 {
1494 // Set key material and cipherAlg to Asic
1495 AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
1496
1497 if (idx == pAd->StaCfg.DefaultKeyId)
1498 {
1499 // Assign group key info
1500 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
1501
1502 // Assign pairwise key info
1503 RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
1504 }
1505 }
1506 }
1507 }
1508
1509 // only INFRASTRUCTURE mode need to indicate connectivity immediately; ADHOC mode
1510 // should wait until at least 2 active nodes in this BSSID.
1511 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1512
1513 // For GUI ++
1514 if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
1515 {
1516 pAd->IndicateMediaState = NdisMediaStateConnected;
1517 pAd->ExtraInfo = GENERAL_LINK_UP;
1518 RTMP_IndicateMediaState(pAd);
1519 }
1520 // --
1521
1522 // Add BSSID in my MAC Table.
1523 NdisAcquireSpinLock(&pAd->MacTabLock);
1524 RTMPMoveMemory(pAd->MacTab.Content[BSSID_WCID].Addr, pAd->CommonCfg.Bssid, MAC_ADDR_LEN);
1525 pAd->MacTab.Content[BSSID_WCID].Aid = BSSID_WCID;
1526 pAd->MacTab.Content[BSSID_WCID].pAd = pAd;
1527 pAd->MacTab.Content[BSSID_WCID].ValidAsCLI = TRUE; //Although this is bssid..still set ValidAsCl
1528 pAd->MacTab.Size = 1; // infra mode always set MACtab size =1.
1529 pAd->MacTab.Content[BSSID_WCID].Sst = SST_ASSOC;
1530 pAd->MacTab.Content[BSSID_WCID].AuthState = SST_ASSOC;
1531#ifdef RT30xx
1532 pAd->MacTab.Content[BSSID_WCID].AuthMode = pAd->StaCfg.AuthMode;
1533#endif
1534 pAd->MacTab.Content[BSSID_WCID].WepStatus = pAd->StaCfg.WepStatus;
1535 NdisReleaseSpinLock(&pAd->MacTabLock);
1536
1537 DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! ClientStatusFlags=%lx)\n",
1538 pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
1539
1540 MlmeUpdateTxRates(pAd, TRUE, BSS0);
1541 MlmeUpdateHtTxRates(pAd, BSS0);
1542 DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !! (StaActive.bHtEnable =%d, )\n", pAd->StaActive.SupportedPhyInfo.bHtEnable));
1543
1544 if (pAd->CommonCfg.bAggregationCapable)
1545 {
1546 if ((pAd->CommonCfg.bPiggyBackCapable) && (pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)
1547 {
1548
1549 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED);
1550 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
1551 RTMPSetPiggyBack(pAd, TRUE);
1552 DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n"));
1553 }
1554 else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
1555 {
1556 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
1557 }
1558 }
1559
1560 if (pAd->MlmeAux.APRalinkIe != 0x0)
1561 {
1562 if (CLIENT_STATUS_TEST_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RDG_CAPABLE))
1563 {
1564 AsicEnableRDG(pAd);
1565 }
1566
1567 OPSTATUS_SET_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET);
1568 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET);
1569 }
1570 else
1571 {
1572 OPSTATUS_CLEAR_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET);
1573 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET);
1574 }
1575 }
1576
1577 DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_CONNECT Event B!.BACapability = %x. ClientStatusFlags = %lx\n", pAd->CommonCfg.BACapability.word, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
1578
1579 // Set LED
1580 RTMPSetLED(pAd, LED_LINK_UP);
1581
1582 pAd->Mlme.PeriodicRound = 0;
1583 pAd->Mlme.OneSecPeriodicRound = 0;
1584 pAd->bConfigChanged = FALSE; // Reset config flag
1585 pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up
1586
1587 // Set asic auto fall back
1588 {
1589 PUCHAR pTable;
1590 UCHAR TableSize = 0;
1591
1592 MlmeSelectTxRateTable(pAd, &pAd->MacTab.Content[BSSID_WCID], &pTable, &TableSize, &pAd->CommonCfg.TxRateIndex);
1593 AsicUpdateAutoFallBackTable(pAd, pTable);
1594 }
1595
1596 NdisAcquireSpinLock(&pAd->MacTabLock);
1597 pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
1598 pEntry->MaxHTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
1599 if (pAd->StaCfg.bAutoTxRateSwitch == FALSE)
1600 {
1601 pEntry->bAutoTxRateSwitch = FALSE;
1602
1603 if (pEntry->HTPhyMode.field.MCS == 32)
1604 pEntry->HTPhyMode.field.ShortGI = GI_800;
1605
1606 if ((pEntry->HTPhyMode.field.MCS > MCS_7) || (pEntry->HTPhyMode.field.MCS == 32))
1607 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1608
1609 // If the legacy mode is set, overwrite the transmit setting of this entry.
1610 if (pEntry->HTPhyMode.field.MODE <= MODE_OFDM)
1611 RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
1612 }
1613 else
1614 pEntry->bAutoTxRateSwitch = TRUE;
1615 NdisReleaseSpinLock(&pAd->MacTabLock);
1616
1617 // Let Link Status Page display first initial rate.
1618 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1619 // Select DAC according to HT or Legacy
1620 if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00)
1621 {
1622 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value);
1623 Value &= (~0x18);
1624 if (pAd->Antenna.field.TxPath == 2)
1625 {
1626 Value |= 0x10;
1627 }
1628 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value);
1629 }
1630 else
1631 {
1632 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value);
1633 Value &= (~0x18);
1634 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value);
1635 }
1636
1637 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
1638 {
1639 }
1640 else if (pEntry->MaxRAmpduFactor == 0)
1641 {
1642 // If HT AP doesn't support MaxRAmpduFactor = 1, we need to set max PSDU to 0.
1643 // Because our Init value is 1 at MACRegTable.
1644 RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x0fff);
1645 }
1646
1647 // Patch for Marvel AP to gain high throughput
1648 // Need to set as following,
1649 // 1. Set txop in register-EDCA_AC0_CFG as 0x60
1650 // 2. Set EnTXWriteBackDDONE in register-WPDMA_GLO_CFG as zero
1651 // 3. PBF_MAX_PCNT as 0x1F3FBF9F
1652 // 4. kick per two packets when dequeue
1653 //
1654 // Txop can only be modified when RDG is off, WMM is disable and TxBurst is enable
1655 //
1656 // if 1. Legacy AP WMM on, or 2. 11n AP, AMPDU disable. Force turn off burst no matter what bEnableTxBurst is.
1657#ifdef RT30xx
1658 if (!((pAd->CommonCfg.RxStream == 1)&&(pAd->CommonCfg.TxStream == 1)) &&
1659 (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
1660 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))))
1661#endif
1662#ifndef RT30xx
1663 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
1664 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)))
1665#endif
1666 {
1667 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
1668 Data &= 0xFFFFFF00;
1669 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
1670
1671 RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F);
1672 DBGPRINT(RT_DEBUG_TRACE, ("Txburst 1\n"));
1673 }
1674 else
1675 if (pAd->CommonCfg.bEnableTxBurst)
1676 {
1677 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
1678 Data &= 0xFFFFFF00;
1679 Data |= 0x60;
1680 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
1681 pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = TRUE;
1682
1683 RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3FBF9F);
1684 DBGPRINT(RT_DEBUG_TRACE, ("Txburst 2\n"));
1685 }
1686 else
1687 {
1688 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
1689 Data &= 0xFFFFFF00;
1690 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
1691
1692 RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F);
1693 DBGPRINT(RT_DEBUG_TRACE, ("Txburst 3\n"));
1694 }
1695
1696 // Re-check to turn on TX burst or not.
1697 if ((pAd->CommonCfg.IOTestParm.bLastAtheros == TRUE) && ((STA_WEP_ON(pAd))||(STA_TKIP_ON(pAd))))
1698 {
1699 pAd->CommonCfg.IOTestParm.bNextDisableRxBA = TRUE;
1700 if (pAd->CommonCfg.bEnableTxBurst)
1701 {
1702 UINT32 MACValue = 0;
1703 // Force disable TXOP value in this case. The same action in MLMEUpdateProtect too.
1704 // I didn't change PBF_MAX_PCNT setting.
1705 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &MACValue);
1706 MACValue &= 0xFFFFFF00;
1707 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, MACValue);
1708 pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE;
1709 }
1710 }
1711 else
1712 {
1713 pAd->CommonCfg.IOTestParm.bNextDisableRxBA = FALSE;
1714 }
1715
1716 pAd->CommonCfg.IOTestParm.bLastAtheros = FALSE;
1717 COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid);
1718 DBGPRINT(RT_DEBUG_TRACE, ("!!!pAd->bNextDisableRxBA= %d \n", pAd->CommonCfg.IOTestParm.bNextDisableRxBA));
1719 // BSSID add in one MAC entry too. Because in Tx, ASIC need to check Cipher and IV/EIV, BAbitmap
1720 // Pther information in MACTab.Content[BSSID_WCID] is not necessary for driver.
1721 // Note: As STA, The MACTab.Content[BSSID_WCID]. PairwiseKey and Shared Key for BSS0 are the same.
1722
1723 if (pAd->StaCfg.WepStatus <= Ndis802_11WEPDisabled)
1724 {
1725 pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
1726 pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1727 }
1728
1729 NdisAcquireSpinLock(&pAd->MacTabLock);
1730 pEntry->PortSecured = pAd->StaCfg.PortSecured;
1731 NdisReleaseSpinLock(&pAd->MacTabLock);
1732
1733 //
1734 // Patch Atheros AP TX will breakdown issue.
1735 // AP Model: DLink DWL-8200AP
1736 //
1737 if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && STA_TKIP_ON(pAd))
1738 {
1739 RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x01);
1740 }
1741 else
1742 {
1743 RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x00);
1744 }
1745
1746 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1747}
1748
1749/*
1750 ==========================================================================
1751
1752 Routine Description:
1753 Disconnect current BSSID
1754
1755 Arguments:
1756 pAd - Pointer to our adapter
1757 IsReqFromAP - Request from AP
1758
1759 Return Value:
1760 None
1761
1762 IRQL = DISPATCH_LEVEL
1763
1764 Note:
1765 We need more information to know it's this requst from AP.
1766 If yes! we need to do extra handling, for example, remove the WPA key.
1767 Otherwise on 4-way handshaking will faied, since the WPA key didn't be
1768 remove while auto reconnect.
1769 Disconnect request from AP, it means we will start afresh 4-way handshaking
1770 on WPA mode.
1771
1772 ==========================================================================
1773*/
1774VOID LinkDown(
1775 IN PRTMP_ADAPTER pAd,
1776 IN BOOLEAN IsReqFromAP)
1777{
1778 UCHAR i, ByteValue = 0;
1779
1780 // Do nothing if monitor mode is on
1781 if (MONITOR_ON(pAd))
1782 return;
1783
1784 if (pAd->CommonCfg.bWirelessEvent)
1785 {
1786 RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1787 }
1788
1789 DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN !!!\n"));
1790 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
1791
1792 if (ADHOC_ON(pAd)) // Adhoc mode link down
1793 {
1794 DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 1!!!\n"));
1795
1796 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
1797 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1798 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1799 RTMP_IndicateMediaState(pAd);
1800 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1801 BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel);
1802 DBGPRINT(RT_DEBUG_TRACE, ("!!! MacTab.Size=%d !!!\n", pAd->MacTab.Size));
1803 }
1804 else // Infra structure mode
1805 {
1806 DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 2!!!\n"));
1807
1808 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
1809 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1810
1811 // Saved last SSID for linkup comparison
1812 pAd->CommonCfg.LastSsidLen = pAd->CommonCfg.SsidLen;
1813 NdisMoveMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen);
1814 COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid);
1815 if (pAd->MlmeAux.CurrReqIsFromNdis == TRUE)
1816 {
1817 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1818 RTMP_IndicateMediaState(pAd);
1819 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1820 DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event A!\n"));
1821 pAd->MlmeAux.CurrReqIsFromNdis = FALSE;
1822 }
1823 else
1824 {
1825 //
1826 // If disassociation request is from NDIS, then we don't need to delete BSSID from entry.
1827 // Otherwise lost beacon or receive De-Authentication from AP,
1828 // then we should delete BSSID from BssTable.
1829 // If we don't delete from entry, roaming will fail.
1830 //
1831 BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel);
1832 }
1833
1834 // restore back to -
1835 // 1. long slot (20 us) or short slot (9 us) time
1836 // 2. turn on/off RTS/CTS and/or CTS-to-self protection
1837 // 3. short preamble
1838 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1839
1840 if (pAd->StaCfg.CCXAdjacentAPReportFlag == TRUE)
1841 {
1842 //
1843 // Record current AP's information.
1844 // for later used reporting Adjacent AP report.
1845 //
1846 pAd->StaCfg.CCXAdjacentAPChannel = pAd->CommonCfg.Channel;
1847 pAd->StaCfg.CCXAdjacentAPSsidLen = pAd->CommonCfg.SsidLen;
1848 NdisMoveMemory(pAd->StaCfg.CCXAdjacentAPSsid, pAd->CommonCfg.Ssid, pAd->StaCfg.CCXAdjacentAPSsidLen);
1849 COPY_MAC_ADDR(pAd->StaCfg.CCXAdjacentAPBssid, pAd->CommonCfg.Bssid);
1850 }
1851 }
1852
1853 for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
1854 {
1855 if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
1856 MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid, pAd->MacTab.Content[i].Addr);
1857 }
1858
1859 pAd->StaCfg.CCXQosECWMin = 4;
1860 pAd->StaCfg.CCXQosECWMax = 10;
1861
1862 AsicSetSlotTime(pAd, TRUE); //FALSE);
1863 AsicSetEdcaParm(pAd, NULL);
1864
1865 // Set LED
1866 RTMPSetLED(pAd, LED_LINK_DOWN);
1867 pAd->LedIndicatorStregth = 0xF0;
1868 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
1869
1870 AsicDisableSync(pAd);
1871
1872 pAd->Mlme.PeriodicRound = 0;
1873 pAd->Mlme.OneSecPeriodicRound = 0;
1874
1875 if (pAd->StaCfg.BssType == BSS_INFRA)
1876 {
1877 // Remove StaCfg Information after link down
1878 NdisZeroMemory(pAd->CommonCfg.Bssid, MAC_ADDR_LEN);
1879 NdisZeroMemory(pAd->CommonCfg.Ssid, MAX_LEN_OF_SSID);
1880 pAd->CommonCfg.SsidLen = 0;
1881 }
1882
1883 NdisZeroMemory(&pAd->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE));
1884 NdisZeroMemory(&pAd->MlmeAux.AddHtInfo, sizeof(ADD_HT_INFO_IE));
1885 pAd->MlmeAux.HtCapabilityLen = 0;
1886 pAd->MlmeAux.NewExtChannelOffset = 0xff;
1887
1888 // Reset WPA-PSK state. Only reset when supplicant enabled
1889 if (pAd->StaCfg.WpaState != SS_NOTUSE)
1890 {
1891 pAd->StaCfg.WpaState = SS_START;
1892 // Clear Replay counter
1893 NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
1894 }
1895
1896
1897 //
1898 // if link down come from AP, we need to remove all WPA keys on WPA mode.
1899 // otherwise will cause 4-way handshaking failed, since the WPA key not empty.
1900 //
1901 if ((IsReqFromAP) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA))
1902 {
1903 // Remove all WPA keys
1904 RTMPWPARemoveAllKeys(pAd);
1905 }
1906
1907 // 802.1x port control
1908
1909 // Prevent clear PortSecured here with static WEP
1910 // NetworkManger set security policy first then set SSID to connect AP.
1911 if (pAd->StaCfg.WpaSupplicantUP &&
1912 (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) &&
1913 (pAd->StaCfg.IEEE8021X == FALSE))
1914 {
1915 pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
1916 }
1917 else
1918 {
1919 pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
1920 pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
1921 }
1922
1923 NdisAcquireSpinLock(&pAd->MacTabLock);
1924 pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.PortSecured;
1925 NdisReleaseSpinLock(&pAd->MacTabLock);
1926
1927 pAd->StaCfg.MicErrCnt = 0;
1928
1929 // Turn off Ckip control flag
1930 pAd->StaCfg.bCkipOn = FALSE;
1931 pAd->StaCfg.CCXEnable = FALSE;
1932
1933 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1934 // Update extra information to link is up
1935 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1936
1937 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
1938
1939 // Reset the Current AP's IP address
1940 NdisZeroMemory(pAd->StaCfg.AironetIPAddress, 4);
1941#ifdef RT2870
1942 pAd->bUsbTxBulkAggre = FALSE;
1943#endif // RT2870 //
1944
1945 // Clean association information
1946 NdisZeroMemory(&pAd->StaCfg.AssocInfo, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION));
1947 pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
1948 pAd->StaCfg.ReqVarIELen = 0;
1949 pAd->StaCfg.ResVarIELen = 0;
1950
1951 //
1952 // Reset RSSI value after link down
1953 //
1954 pAd->StaCfg.RssiSample.AvgRssi0 = 0;
1955 pAd->StaCfg.RssiSample.AvgRssi0X8 = 0;
1956 pAd->StaCfg.RssiSample.AvgRssi1 = 0;
1957 pAd->StaCfg.RssiSample.AvgRssi1X8 = 0;
1958 pAd->StaCfg.RssiSample.AvgRssi2 = 0;
1959 pAd->StaCfg.RssiSample.AvgRssi2X8 = 0;
1960
1961 // Restore MlmeRate
1962 pAd->CommonCfg.MlmeRate = pAd->CommonCfg.BasicMlmeRate;
1963 pAd->CommonCfg.RtsRate = pAd->CommonCfg.BasicMlmeRate;
1964
1965 //
1966 // After Link down, reset piggy-back setting in ASIC. Disable RDG.
1967 //
1968 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
1969 {
1970 pAd->CommonCfg.BBPCurrentBW = BW_20;
1971 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &ByteValue);
1972 ByteValue &= (~0x18);
1973 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, ByteValue);
1974 }
1975
1976 // Reset DAC
1977 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &ByteValue);
1978 ByteValue &= (~0x18);
1979 if (pAd->Antenna.field.TxPath == 2)
1980 {
1981 ByteValue |= 0x10;
1982 }
1983 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, ByteValue);
1984
1985 RTMPSetPiggyBack(pAd,FALSE);
1986 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED);
1987
1988 pAd->CommonCfg.BACapability.word = pAd->CommonCfg.REGBACapability.word;
1989
1990 // Restore all settings in the following.
1991 AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE);
1992 AsicDisableRDG(pAd);
1993 pAd->CommonCfg.IOTestParm.bCurrentAtheros = FALSE;
1994 pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE;
1995
1996 RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x1fff);
1997 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
1998
1999 {
2000 union iwreq_data wrqu;
2001 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
2002 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
2003 }
2004
2005#ifdef RT30xx
2006 if (IS_RT3090(pAd))
2007 {
2008 UINT32 macdata;
2009 // disable MMPS BBP control register
2010 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &ByteValue);
2011 ByteValue &= ~(0x04); //bit 2
2012 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, ByteValue);
2013
2014 // disable MMPS MAC control register
2015 RTMP_IO_READ32(pAd, 0x1210, &macdata);
2016 macdata &= ~(0x09); //bit 0, 3
2017 RTMP_IO_WRITE32(pAd, 0x1210, macdata);
2018 }
2019#endif // RT30xx //
2020}
2021
2022/*
2023 ==========================================================================
2024 Description:
2025
2026 IRQL = DISPATCH_LEVEL
2027
2028 ==========================================================================
2029*/
2030VOID IterateOnBssTab(
2031 IN PRTMP_ADAPTER pAd)
2032{
2033 MLME_START_REQ_STRUCT StartReq;
2034 MLME_JOIN_REQ_STRUCT JoinReq;
2035 ULONG BssIdx;
2036
2037 // Change the wepstatus to original wepstatus
2038 pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus;
2039 pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus;
2040 pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus;
2041
2042 BssIdx = pAd->MlmeAux.BssIdx;
2043 if (BssIdx < pAd->MlmeAux.SsidBssTab.BssNr)
2044 {
2045 // Check cipher suite, AP must have more secured cipher than station setting
2046 // Set the Pairwise and Group cipher to match the intended AP setting
2047 // We can only connect to AP with less secured cipher setting
2048 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
2049 {
2050 pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.GroupCipher;
2051
2052 if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher)
2053 pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher;
2054 else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled)
2055 pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux;
2056 else // There is no PairCipher Aux, downgrade our capability to TKIP
2057 pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
2058 }
2059 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
2060 {
2061 pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.GroupCipher;
2062
2063 if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher)
2064 pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher;
2065 else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled)
2066 pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux;
2067 else // There is no PairCipher Aux, downgrade our capability to TKIP
2068 pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
2069
2070 // RSN capability
2071 pAd->StaCfg.RsnCapability = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.RsnCapability;
2072 }
2073
2074 // Set Mix cipher flag
2075 pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE;
2076 if (pAd->StaCfg.bMixCipher == TRUE)
2077 {
2078 // If mix cipher, re-build RSNIE
2079 RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0);
2080 }
2081
2082 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.SsidBssTab.BssNr));
2083 JoinParmFill(pAd, &JoinReq, BssIdx);
2084 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT),
2085 &JoinReq);
2086 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN;
2087 }
2088 else if (pAd->StaCfg.BssType == BSS_ADHOC)
2089 {
2090 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All BSS fail; start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid));
2091 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
2092 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
2093 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
2094 }
2095 else // no more BSS
2096 {
2097 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All roaming failed, stay @ ch #%d\n", pAd->CommonCfg.Channel));
2098 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
2099 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
2100 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
2101 }
2102}
2103
2104// for re-association only
2105// IRQL = DISPATCH_LEVEL
2106VOID IterateOnBssTab2(
2107 IN PRTMP_ADAPTER pAd)
2108{
2109 MLME_REASSOC_REQ_STRUCT ReassocReq;
2110 ULONG BssIdx;
2111 BSS_ENTRY *pBss;
2112
2113 BssIdx = pAd->MlmeAux.RoamIdx;
2114 pBss = &pAd->MlmeAux.RoamTab.BssEntry[BssIdx];
2115
2116 if (BssIdx < pAd->MlmeAux.RoamTab.BssNr)
2117 {
2118 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.RoamTab.BssNr));
2119
2120 AsicSwitchChannel(pAd, pBss->Channel, FALSE);
2121 AsicLockChannel(pAd, pBss->Channel);
2122
2123 // reassociate message has the same structure as associate message
2124 AssocParmFill(pAd, &ReassocReq, pBss->Bssid, pBss->CapabilityInfo,
2125 ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount);
2126 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ,
2127 sizeof(MLME_REASSOC_REQ_STRUCT), &ReassocReq);
2128
2129 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC;
2130 }
2131 else // no more BSS
2132 {
2133 DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All fast roaming failed, back to ch #%d\n",pAd->CommonCfg.Channel));
2134 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
2135 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
2136 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
2137 }
2138}
2139
2140/*
2141 ==========================================================================
2142 Description:
2143
2144 IRQL = DISPATCH_LEVEL
2145
2146 ==========================================================================
2147*/
2148VOID JoinParmFill(
2149 IN PRTMP_ADAPTER pAd,
2150 IN OUT MLME_JOIN_REQ_STRUCT *JoinReq,
2151 IN ULONG BssIdx)
2152{
2153 JoinReq->BssIdx = BssIdx;
2154}
2155
2156/*
2157 ==========================================================================
2158 Description:
2159
2160 IRQL = DISPATCH_LEVEL
2161
2162 ==========================================================================
2163*/
2164VOID ScanParmFill(
2165 IN PRTMP_ADAPTER pAd,
2166 IN OUT MLME_SCAN_REQ_STRUCT *ScanReq,
2167 IN CHAR Ssid[],
2168 IN UCHAR SsidLen,
2169 IN UCHAR BssType,
2170 IN UCHAR ScanType)
2171{
2172 NdisZeroMemory(ScanReq->Ssid, MAX_LEN_OF_SSID);
2173 ScanReq->SsidLen = SsidLen;
2174 NdisMoveMemory(ScanReq->Ssid, Ssid, SsidLen);
2175 ScanReq->BssType = BssType;
2176 ScanReq->ScanType = ScanType;
2177}
2178
2179/*
2180 ==========================================================================
2181 Description:
2182
2183 IRQL = DISPATCH_LEVEL
2184
2185 ==========================================================================
2186*/
2187VOID StartParmFill(
2188 IN PRTMP_ADAPTER pAd,
2189 IN OUT MLME_START_REQ_STRUCT *StartReq,
2190 IN CHAR Ssid[],
2191 IN UCHAR SsidLen)
2192{
2193 ASSERT(SsidLen <= MAX_LEN_OF_SSID);
2194 NdisMoveMemory(StartReq->Ssid, Ssid, SsidLen);
2195 StartReq->SsidLen = SsidLen;
2196}
2197
2198/*
2199 ==========================================================================
2200 Description:
2201
2202 IRQL = DISPATCH_LEVEL
2203
2204 ==========================================================================
2205*/
2206VOID AuthParmFill(
2207 IN PRTMP_ADAPTER pAd,
2208 IN OUT MLME_AUTH_REQ_STRUCT *AuthReq,
2209 IN PUCHAR pAddr,
2210 IN USHORT Alg)
2211{
2212 COPY_MAC_ADDR(AuthReq->Addr, pAddr);
2213 AuthReq->Alg = Alg;
2214 AuthReq->Timeout = AUTH_TIMEOUT;
2215}
2216
2217/*
2218 ==========================================================================
2219 Description:
2220
2221 IRQL = DISPATCH_LEVEL
2222
2223 ==========================================================================
2224 */
2225
2226
2227#ifdef RT2870
2228
2229VOID MlmeCntlConfirm(
2230 IN PRTMP_ADAPTER pAd,
2231 IN ULONG MsgType,
2232 IN USHORT Msg)
2233{
2234 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MsgType, sizeof(USHORT), &Msg);
2235}
2236
2237VOID ComposePsPoll(
2238 IN PRTMP_ADAPTER pAd)
2239{
2240 PTXINFO_STRUC pTxInfo;
2241 PTXWI_STRUC pTxWI;
2242
2243 DBGPRINT(RT_DEBUG_TRACE, ("ComposePsPoll\n"));
2244 NdisZeroMemory(&pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
2245
2246 pAd->PsPollFrame.FC.PwrMgmt = 0;
2247 pAd->PsPollFrame.FC.Type = BTYPE_CNTL;
2248 pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL;
2249 pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000;
2250 COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid);
2251 COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress);
2252
2253 RTMPZeroMemory(&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[0], 100);
2254 pTxInfo = (PTXINFO_STRUC)&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[0];
2255 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(PSPOLL_FRAME)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
2256 pTxWI = (PTXWI_STRUC)&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE];
2257 RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(PSPOLL_FRAME)),
2258 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
2259 RTMPMoveMemory(&pAd->PsPollContext.TransferBuffer->field.WirelessPacket[TXWI_SIZE+TXINFO_SIZE], &pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
2260 // Append 4 extra zero bytes.
2261 pAd->PsPollContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(PSPOLL_FRAME) + 4;
2262}
2263
2264// IRQL = DISPATCH_LEVEL
2265VOID ComposeNullFrame(
2266 IN PRTMP_ADAPTER pAd)
2267{
2268 PTXINFO_STRUC pTxInfo;
2269 PTXWI_STRUC pTxWI;
2270
2271 NdisZeroMemory(&pAd->NullFrame, sizeof(HEADER_802_11));
2272 pAd->NullFrame.FC.Type = BTYPE_DATA;
2273 pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC;
2274 pAd->NullFrame.FC.ToDs = 1;
2275 COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid);
2276 COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress);
2277 COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid);
2278 RTMPZeroMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[0], 100);
2279 pTxInfo = (PTXINFO_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[0];
2280 RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(sizeof(HEADER_802_11)+TXWI_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE);
2281 pTxWI = (PTXWI_STRUC)&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXINFO_SIZE];
2282 RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, (sizeof(HEADER_802_11)),
2283 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
2284 RTMPMoveMemory(&pAd->NullContext.TransferBuffer->field.WirelessPacket[TXWI_SIZE+TXINFO_SIZE], &pAd->NullFrame, sizeof(HEADER_802_11));
2285 pAd->NullContext.BulkOutSize = TXINFO_SIZE + TXWI_SIZE + sizeof(pAd->NullFrame) + 4;
2286}
2287#endif // RT2870 //
2288
2289
2290/*
2291 ==========================================================================
2292 Description:
2293 Pre-build a BEACON frame in the shared memory
2294
2295 IRQL = PASSIVE_LEVEL
2296 IRQL = DISPATCH_LEVEL
2297
2298 ==========================================================================
2299*/
2300ULONG MakeIbssBeacon(
2301 IN PRTMP_ADAPTER pAd)
2302{
2303 UCHAR DsLen = 1, IbssLen = 2;
2304 UCHAR LocalErpIe[3] = {IE_ERP, 1, 0x04};
2305 HEADER_802_11 BcnHdr;
2306 USHORT CapabilityInfo;
2307 LARGE_INTEGER FakeTimestamp;
2308 ULONG FrameLen = 0;
2309 PTXWI_STRUC pTxWI = &pAd->BeaconTxWI;
2310 CHAR *pBeaconFrame = pAd->BeaconBuf;
2311 BOOLEAN Privacy;
2312 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES];
2313 UCHAR SupRateLen = 0;
2314 UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
2315 UCHAR ExtRateLen = 0;
2316 UCHAR RSNIe = IE_WPA;
2317
2318 if ((pAd->CommonCfg.PhyMode == PHY_11B) && (pAd->CommonCfg.Channel <= 14))
2319 {
2320 SupRate[0] = 0x82; // 1 mbps
2321 SupRate[1] = 0x84; // 2 mbps
2322 SupRate[2] = 0x8b; // 5.5 mbps
2323 SupRate[3] = 0x96; // 11 mbps
2324 SupRateLen = 4;
2325 ExtRateLen = 0;
2326 }
2327 else if (pAd->CommonCfg.Channel > 14)
2328 {
2329 SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate
2330 SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps
2331 SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate
2332 SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps
2333 SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate
2334 SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps
2335 SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps
2336 SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps
2337 SupRateLen = 8;
2338 ExtRateLen = 0;
2339
2340 //
2341 // Also Update MlmeRate & RtsRate for G only & A only
2342 //
2343 pAd->CommonCfg.MlmeRate = RATE_6;
2344 pAd->CommonCfg.RtsRate = RATE_6;
2345 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
2346 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2347 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
2348 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
2349 }
2350 else
2351 {
2352 SupRate[0] = 0x82; // 1 mbps
2353 SupRate[1] = 0x84; // 2 mbps
2354 SupRate[2] = 0x8b; // 5.5 mbps
2355 SupRate[3] = 0x96; // 11 mbps
2356 SupRateLen = 4;
2357
2358 ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps,
2359 ExtRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps
2360 ExtRate[2] = 0x18; // 12 mbps, in units of 0.5 Mbps,
2361 ExtRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps
2362 ExtRate[4] = 0x30; // 24 mbps, in units of 0.5 Mbps,
2363 ExtRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps
2364 ExtRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps
2365 ExtRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps
2366 ExtRateLen = 8;
2367 }
2368
2369 pAd->StaActive.SupRateLen = SupRateLen;
2370 NdisMoveMemory(pAd->StaActive.SupRate, SupRate, SupRateLen);
2371 pAd->StaActive.ExtRateLen = ExtRateLen;
2372 NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, ExtRateLen);
2373
2374 // compose IBSS beacon frame
2375 MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->CommonCfg.Bssid);
2376 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
2377 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
2378 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
2379 CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0);
2380
2381 MakeOutgoingFrame(pBeaconFrame, &FrameLen,
2382 sizeof(HEADER_802_11), &BcnHdr,
2383 TIMESTAMP_LEN, &FakeTimestamp,
2384 2, &pAd->CommonCfg.BeaconPeriod,
2385 2, &CapabilityInfo,
2386 1, &SsidIe,
2387 1, &pAd->CommonCfg.SsidLen,
2388 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
2389 1, &SupRateIe,
2390 1, &SupRateLen,
2391 SupRateLen, SupRate,
2392 1, &DsIe,
2393 1, &DsLen,
2394 1, &pAd->CommonCfg.Channel,
2395 1, &IbssIe,
2396 1, &IbssLen,
2397 2, &pAd->StaActive.AtimWin,
2398 END_OF_ARGS);
2399
2400 // add ERP_IE and EXT_RAE IE of in 802.11g
2401 if (ExtRateLen)
2402 {
2403 ULONG tmp;
2404
2405 MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp,
2406 3, LocalErpIe,
2407 1, &ExtRateIe,
2408 1, &ExtRateLen,
2409 ExtRateLen, ExtRate,
2410 END_OF_ARGS);
2411 FrameLen += tmp;
2412 }
2413
2414 // If adhoc secruity is set for WPA-None, append the cipher suite IE
2415 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
2416 {
2417 ULONG tmp;
2418 RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0);
2419
2420 MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp,
2421 1, &RSNIe,
2422 1, &pAd->StaCfg.RSNIE_Len,
2423 pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
2424 END_OF_ARGS);
2425 FrameLen += tmp;
2426 }
2427
2428 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
2429 {
2430 ULONG TmpLen;
2431 UCHAR HtLen, HtLen1;
2432
2433 // add HT Capability IE
2434 HtLen = sizeof(pAd->CommonCfg.HtCapability);
2435 HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo);
2436
2437 MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen,
2438 1, &HtCapIe,
2439 1, &HtLen,
2440 HtLen, &pAd->CommonCfg.HtCapability,
2441 1, &AddHtInfoIe,
2442 1, &HtLen1,
2443 HtLen1, &pAd->CommonCfg.AddHTInfo,
2444 END_OF_ARGS);
2445
2446 FrameLen += TmpLen;
2447 }
2448
2449 //beacon use reserved WCID 0xff
2450 if (pAd->CommonCfg.Channel > 14)
2451 {
2452 RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen,
2453 PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
2454 }
2455 else
2456 {
2457 // Set to use 1Mbps for Adhoc beacon.
2458 HTTRANSMIT_SETTING Transmit;
2459 Transmit.word = 0;
2460 RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen,
2461 PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &Transmit);
2462 }
2463
2464 DBGPRINT(RT_DEBUG_TRACE, ("MakeIbssBeacon (len=%ld), SupRateLen=%d, ExtRateLen=%d, Channel=%d, PhyMode=%d\n",
2465 FrameLen, SupRateLen, ExtRateLen, pAd->CommonCfg.Channel, pAd->CommonCfg.PhyMode));
2466 return FrameLen;
2467}
2468
2469
diff --git a/drivers/staging/rt2870/sta/rtmp_data.c b/drivers/staging/rt2870/sta/rtmp_data.c
index 10cb64daba44..b67e06952bcf 100644
--- a/drivers/staging/rt2870/sta/rtmp_data.c
+++ b/drivers/staging/rt2870/sta/rtmp_data.c
@@ -1,2428 +1 @@
1/* #include "../../rt2860/sta/rtmp_data.c"
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 rtmp_data.c
29
30 Abstract:
31 Data path subroutines
32
33 Revision History:
34 Who When What
35 -------- ---------- ----------------------------------------------
36 John Aug/17/04 major modification for RT2561/2661
37 Jan Lee Mar/17/06 major modification for RT2860 New Ring Design
38*/
39#include "../rt_config.h"
40
41
42VOID STARxEAPOLFrameIndicate(
43 IN PRTMP_ADAPTER pAd,
44 IN MAC_TABLE_ENTRY *pEntry,
45 IN RX_BLK *pRxBlk,
46 IN UCHAR FromWhichBSSID)
47{
48 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
49 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
50 UCHAR *pTmpBuf;
51
52 if (pAd->StaCfg.WpaSupplicantUP)
53 {
54 // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
55 // TBD : process fragmented EAPol frames
56 {
57 // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
58 if ( pAd->StaCfg.IEEE8021X == TRUE &&
59 (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
60 {
61 PUCHAR Key;
62 UCHAR CipherAlg;
63 int idx = 0;
64
65 DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
66 STA_PORT_SECURED(pAd);
67
68 if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
69 {
70 idx = pAd->StaCfg.DesireSharedKeyId;
71 CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
72 Key = pAd->StaCfg.DesireSharedKey[idx].Key;
73
74 if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
75 {
76#ifdef RT2870
77 union
78 {
79 char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1];
80 NDIS_802_11_WEP keyinfo;
81 } WepKey;
82 int len;
83
84
85 NdisZeroMemory(&WepKey, sizeof(WepKey));
86 len =pAd->StaCfg.DesireSharedKey[idx].KeyLen;
87
88 NdisMoveMemory(WepKey.keyinfo.KeyMaterial,
89 pAd->StaCfg.DesireSharedKey[idx].Key,
90 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
91
92 WepKey.keyinfo.KeyIndex = 0x80000000 + idx;
93 WepKey.keyinfo.KeyLength = len;
94 pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13);
95
96 pAd->IndicateMediaState = NdisMediaStateConnected;
97 pAd->ExtraInfo = GENERAL_LINK_UP;
98 // need to enqueue cmd to thread
99 RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1);
100#endif // RT2870 //
101 // For Preventing ShardKey Table is cleared by remove key procedure.
102 pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
103 pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
104 NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
105 pAd->StaCfg.DesireSharedKey[idx].Key,
106 pAd->StaCfg.DesireSharedKey[idx].KeyLen);
107 }
108 }
109 }
110
111 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
112 return;
113 }
114 }
115 else
116 {
117 // Special DATA frame that has to pass to MLME
118 // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
119 // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
120 {
121 pTmpBuf = pRxBlk->pData - LENGTH_802_11;
122 NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
123 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
124 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
125 }
126 }
127
128 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
129 return;
130
131}
132
133VOID STARxDataFrameAnnounce(
134 IN PRTMP_ADAPTER pAd,
135 IN MAC_TABLE_ENTRY *pEntry,
136 IN RX_BLK *pRxBlk,
137 IN UCHAR FromWhichBSSID)
138{
139
140 // non-EAP frame
141 if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
142 {
143 {
144 // drop all non-EAP DATA frame before
145 // this client's Port-Access-Control is secured
146 if (pRxBlk->pHeader->FC.Wep)
147 {
148 // unsupported cipher suite
149 if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
150 {
151 // release packet
152 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
153 return;
154 }
155 }
156 else
157 {
158 // encryption in-use but receive a non-EAPOL clear text frame, drop it
159 if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
160 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
161 {
162 // release packet
163 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
164 return;
165 }
166 }
167 }
168 RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
169 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
170 {
171 // Normal legacy, AMPDU or AMSDU
172 CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
173
174 }
175 else
176 {
177 // ARALINK
178 CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
179 }
180 }
181 else
182 {
183 RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
184
185 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
186 {
187 Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
188 }
189 else
190 {
191 // Determin the destination of the EAP frame
192 // to WPA state machine or upper layer
193 STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
194 }
195 }
196}
197
198
199// For TKIP frame, calculate the MIC value
200BOOLEAN STACheckTkipMICValue(
201 IN PRTMP_ADAPTER pAd,
202 IN MAC_TABLE_ENTRY *pEntry,
203 IN RX_BLK *pRxBlk)
204{
205 PHEADER_802_11 pHeader = pRxBlk->pHeader;
206 UCHAR *pData = pRxBlk->pData;
207 USHORT DataSize = pRxBlk->DataSize;
208 UCHAR UserPriority = pRxBlk->UserPriority;
209 PCIPHER_KEY pWpaKey;
210 UCHAR *pDA, *pSA;
211
212 pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
213
214 pDA = pHeader->Addr1;
215 if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
216 {
217 pSA = pHeader->Addr3;
218 }
219 else
220 {
221 pSA = pHeader->Addr2;
222 }
223
224 if (RTMPTkipCompareMICValue(pAd,
225 pData,
226 pDA,
227 pSA,
228 pWpaKey->RxMic,
229 UserPriority,
230 DataSize) == FALSE)
231 {
232 DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
233
234 if (pAd->StaCfg.WpaSupplicantUP)
235 {
236 WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
237 }
238 else
239 {
240 RTMPReportMicError(pAd, pWpaKey);
241 }
242
243 // release packet
244 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
245 return FALSE;
246 }
247
248 return TRUE;
249}
250
251
252//
253// All Rx routines use RX_BLK structure to hande rx events
254// It is very important to build pRxBlk attributes
255// 1. pHeader pointer to 802.11 Header
256// 2. pData pointer to payload including LLC (just skip Header)
257// 3. set payload size including LLC to DataSize
258// 4. set some flags with RX_BLK_SET_FLAG()
259//
260VOID STAHandleRxDataFrame(
261 IN PRTMP_ADAPTER pAd,
262 IN RX_BLK *pRxBlk)
263{
264 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
265 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
266 PHEADER_802_11 pHeader = pRxBlk->pHeader;
267 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
268 BOOLEAN bFragment = FALSE;
269 MAC_TABLE_ENTRY *pEntry = NULL;
270 UCHAR FromWhichBSSID = BSS0;
271 UCHAR UserPriority = 0;
272
273 {
274 // before LINK UP, all DATA frames are rejected
275 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
276 {
277 // release packet
278 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
279 return;
280 }
281
282 // Drop not my BSS frames
283 if (pRxD->MyBss == 0)
284 {
285 {
286 // release packet
287 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
288 return;
289 }
290 }
291
292 pAd->RalinkCounters.RxCountSinceLastNULL++;
293 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
294 {
295 UCHAR *pData;
296 DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
297
298 // Qos bit 4
299 pData = (PUCHAR)pHeader + LENGTH_802_11;
300 if ((*pData >> 4) & 0x01)
301 {
302 DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
303 pAd->CommonCfg.bInServicePeriod = FALSE;
304
305 // Force driver to fall into sleep mode when rcv EOSP frame
306 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
307 {
308 USHORT TbttNumToNextWakeUp;
309 USHORT NextDtim = pAd->StaCfg.DtimPeriod;
310 ULONG Now;
311
312 NdisGetSystemUpTime(&Now);
313 NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
314
315 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
316 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
317 TbttNumToNextWakeUp = NextDtim;
318
319 MlmeSetPsmBit(pAd, PWR_SAVE);
320 // if WMM-APSD is failed, try to disable following line
321 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
322 }
323 }
324
325 if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
326 {
327 DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
328 }
329 }
330
331 // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
332 if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
333 {
334 // release packet
335 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
336 return;
337 }
338
339 // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
340
341 if (INFRA_ON(pAd))
342 {
343 // Infrastructure mode, check address 2 for BSSID
344 if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
345 {
346 // Receive frame not my BSSID
347 // release packet
348 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
349 return;
350 }
351 }
352 else // Ad-Hoc mode or Not associated
353 {
354 // Ad-Hoc mode, check address 3 for BSSID
355 if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
356 {
357 // Receive frame not my BSSID
358 // release packet
359 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
360 return;
361 }
362 }
363
364 //
365 // find pEntry
366 //
367 if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
368 {
369 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
370 }
371 else
372 {
373 // 1. release packet if infra mode
374 // 2. new a pEntry if ad-hoc mode
375 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
376 return;
377 }
378
379 // infra or ad-hoc
380 if (INFRA_ON(pAd))
381 {
382 RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
383 ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
384 }
385
386 // check Atheros Client
387 if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
388 {
389 pEntry->bIAmBadAtheros = TRUE;
390 pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
391 pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
392 if (!STA_AES_ON(pAd))
393 {
394 AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
395 }
396 }
397 }
398
399 pRxBlk->pData = (UCHAR *)pHeader;
400
401 //
402 // update RxBlk->pData, DataSize
403 // 802.11 Header, QOS, HTC, Hw Padding
404 //
405
406 // 1. skip 802.11 HEADER
407 {
408 pRxBlk->pData += LENGTH_802_11;
409 pRxBlk->DataSize -= LENGTH_802_11;
410 }
411
412 // 2. QOS
413 if (pHeader->FC.SubType & 0x08)
414 {
415 RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
416 UserPriority = *(pRxBlk->pData) & 0x0f;
417 // bit 7 in QoS Control field signals the HT A-MSDU format
418 if ((*pRxBlk->pData) & 0x80)
419 {
420 RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
421 }
422
423 // skip QOS contorl field
424 pRxBlk->pData += 2;
425 pRxBlk->DataSize -=2;
426 }
427 pRxBlk->UserPriority = UserPriority;
428
429 // 3. Order bit: A-Ralink or HTC+
430 if (pHeader->FC.Order)
431 {
432#ifdef AGGREGATION_SUPPORT
433 if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
434 {
435 RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
436 }
437 else
438#endif
439 {
440 RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
441 // skip HTC contorl field
442 pRxBlk->pData += 4;
443 pRxBlk->DataSize -= 4;
444 }
445 }
446
447 // 4. skip HW padding
448 if (pRxD->L2PAD)
449 {
450 // just move pData pointer
451 // because DataSize excluding HW padding
452 RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
453 pRxBlk->pData += 2;
454 }
455
456 if (pRxD->BA)
457 {
458 RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
459 }
460
461 //
462 // Case I Process Broadcast & Multicast data frame
463 //
464 if (pRxD->Bcast || pRxD->Mcast)
465 {
466 INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
467
468 // Drop Mcast/Bcast frame with fragment bit on
469 if (pHeader->FC.MoreFrag)
470 {
471 // release packet
472 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
473 return;
474 }
475
476 // Filter out Bcast frame which AP relayed for us
477 if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
478 {
479 // release packet
480 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
481 return;
482 }
483
484 Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
485 return;
486 }
487 else if (pRxD->U2M)
488 {
489 pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
490
491 if (ADHOC_ON(pAd))
492 {
493 pEntry = MacTableLookup(pAd, pHeader->Addr2);
494 if (pEntry)
495 Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
496 }
497
498
499 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
500
501 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
502 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
503
504 pAd->RalinkCounters.OneSecRxOkDataCnt++;
505
506
507 if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
508 {
509 // re-assemble the fragmented packets
510 // return complete frame (pRxPacket) or NULL
511 bFragment = TRUE;
512 pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
513 }
514
515 if (pRxPacket)
516 {
517 pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
518
519 // process complete frame
520 if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
521 {
522 // Minus MIC length
523 pRxBlk->DataSize -= 8;
524
525 // For TKIP frame, calculate the MIC value
526 if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
527 {
528 return;
529 }
530 }
531
532 STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
533 return;
534 }
535 else
536 {
537 // just return
538 // because RTMPDeFragmentDataFrame() will release rx packet,
539 // if packet is fragmented
540 return;
541 }
542 }
543
544 ASSERT(0);
545 // release packet
546 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
547}
548
549VOID STAHandleRxMgmtFrame(
550 IN PRTMP_ADAPTER pAd,
551 IN RX_BLK *pRxBlk)
552{
553 PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
554 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
555 PHEADER_802_11 pHeader = pRxBlk->pHeader;
556 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
557
558 do
559 {
560
561 // We should collect RSSI not only U2M data but also my beacon
562#ifdef RT30xx
563 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))
564 && (pAd->RxAnt.EvaluatePeriod == 0))
565#endif
566#ifndef RT30xx
567 if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
568#endif
569 {
570 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
571
572 pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
573 pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
574 }
575
576#ifdef RT30xx
577 // collect rssi information for antenna diversity
578 if (pAd->NicConfig2.field.AntDiversity)
579 {
580 if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2))))
581 {
582 COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxWI->RSSI0, RSSI_0), 0); //Note: RSSI2 not used on RT73
583 pAd->StaCfg.NumOfAvgRssiSample ++;
584 }
585 }
586#endif // RT30xx //
587
588 // First check the size, it MUST not exceed the mlme queue size
589 if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
590 {
591 DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
592 break;
593 }
594
595 REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
596 pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
597 } while (FALSE);
598
599 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
600}
601
602VOID STAHandleRxControlFrame(
603 IN PRTMP_ADAPTER pAd,
604 IN RX_BLK *pRxBlk)
605{
606 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
607 PHEADER_802_11 pHeader = pRxBlk->pHeader;
608 PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
609
610 switch (pHeader->FC.SubType)
611 {
612 case SUBTYPE_BLOCK_ACK_REQ:
613 {
614 CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
615 }
616 break;
617 case SUBTYPE_BLOCK_ACK:
618 case SUBTYPE_ACK:
619 default:
620 break;
621 }
622
623 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
624}
625
626
627/*
628 ========================================================================
629
630 Routine Description:
631 Process RxDone interrupt, running in DPC level
632
633 Arguments:
634 pAd Pointer to our adapter
635
636 Return Value:
637 None
638
639 IRQL = DISPATCH_LEVEL
640
641 Note:
642 This routine has to maintain Rx ring read pointer.
643 Need to consider QOS DATA format when converting to 802.3
644 ========================================================================
645*/
646BOOLEAN STARxDoneInterruptHandle(
647 IN PRTMP_ADAPTER pAd,
648 IN BOOLEAN argc)
649{
650 NDIS_STATUS Status;
651 UINT32 RxProcessed, RxPending;
652 BOOLEAN bReschedule = FALSE;
653 RT28XX_RXD_STRUC *pRxD;
654 UCHAR *pData;
655 PRXWI_STRUC pRxWI;
656 PNDIS_PACKET pRxPacket;
657 PHEADER_802_11 pHeader;
658 RX_BLK RxCell;
659
660 RxProcessed = RxPending = 0;
661
662 // process whole rx ring
663 while (1)
664 {
665
666 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
667 fRTMP_ADAPTER_RESET_IN_PROGRESS |
668 fRTMP_ADAPTER_HALT_IN_PROGRESS |
669 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
670 !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
671 {
672 break;
673 }
674
675
676 RxProcessed ++; // test
677
678 // 1. allocate a new data packet into rx ring to replace received packet
679 // then processing the received packet
680 // 2. the callee must take charge of release of packet
681 // 3. As far as driver is concerned ,
682 // the rx packet must
683 // a. be indicated to upper layer or
684 // b. be released if it is discarded
685 pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
686 if (pRxPacket == NULL)
687 {
688 // no more packet to process
689 break;
690 }
691
692 // get rx ring descriptor
693 pRxD = &(RxCell.RxD);
694 // get rx data buffer
695 pData = GET_OS_PKT_DATAPTR(pRxPacket);
696 pRxWI = (PRXWI_STRUC) pData;
697 pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
698
699 // build RxCell
700 RxCell.pRxWI = pRxWI;
701 RxCell.pHeader = pHeader;
702 RxCell.pRxPacket = pRxPacket;
703 RxCell.pData = (UCHAR *) pHeader;
704 RxCell.DataSize = pRxWI->MPDUtotalByteCount;
705 RxCell.Flags = 0;
706
707 // Increase Total receive byte counter after real data received no mater any error or not
708 pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
709 pAd->RalinkCounters.RxCount ++;
710
711 INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
712
713 if (pRxWI->MPDUtotalByteCount < 14)
714 Status = NDIS_STATUS_FAILURE;
715
716 if (MONITOR_ON(pAd))
717 {
718 send_monitor_packets(pAd, &RxCell);
719 break;
720 }
721 /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
722
723 // Check for all RxD errors
724 Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
725
726 // Handle the received frame
727 if (Status == NDIS_STATUS_SUCCESS)
728 {
729 switch (pHeader->FC.Type)
730 {
731 // CASE I, receive a DATA frame
732 case BTYPE_DATA:
733 {
734 // process DATA frame
735 STAHandleRxDataFrame(pAd, &RxCell);
736 }
737 break;
738 // CASE II, receive a MGMT frame
739 case BTYPE_MGMT:
740 {
741 STAHandleRxMgmtFrame(pAd, &RxCell);
742 }
743 break;
744 // CASE III. receive a CNTL frame
745 case BTYPE_CNTL:
746 {
747 STAHandleRxControlFrame(pAd, &RxCell);
748 }
749 break;
750 // discard other type
751 default:
752 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
753 break;
754 }
755 }
756 else
757 {
758 pAd->Counters8023.RxErrors++;
759 // discard this frame
760 RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
761 }
762 }
763
764 return bReschedule;
765}
766
767/*
768 ========================================================================
769
770 Routine Description:
771 Arguments:
772 pAd Pointer to our adapter
773
774 IRQL = DISPATCH_LEVEL
775
776 ========================================================================
777*/
778VOID RTMPHandleTwakeupInterrupt(
779 IN PRTMP_ADAPTER pAd)
780{
781 AsicForceWakeup(pAd, FALSE);
782}
783
784/*
785========================================================================
786Routine Description:
787 Early checking and OS-depened parsing for Tx packet send to our STA driver.
788
789Arguments:
790 NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
791 PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
792 UINT NumberOfPackets Number of packet in packet array.
793
794Return Value:
795 NONE
796
797Note:
798 This function do early checking and classification for send-out packet.
799 You only can put OS-depened & STA related code in here.
800========================================================================
801*/
802VOID STASendPackets(
803 IN NDIS_HANDLE MiniportAdapterContext,
804 IN PPNDIS_PACKET ppPacketArray,
805 IN UINT NumberOfPackets)
806{
807 UINT Index;
808 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
809 PNDIS_PACKET pPacket;
810 BOOLEAN allowToSend = FALSE;
811
812
813 for (Index = 0; Index < NumberOfPackets; Index++)
814 {
815 pPacket = ppPacketArray[Index];
816
817 do
818 {
819 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
820 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
821 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
822 {
823 // Drop send request since hardware is in reset state
824 break;
825 }
826 else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
827 {
828 // Drop send request since there are no physical connection yet
829 break;
830 }
831 else
832 {
833 // Record that orignal packet source is from NDIS layer,so that
834 // later on driver knows how to release this NDIS PACKET
835 RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
836 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
837 NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
838 pAd->RalinkCounters.PendingNdisPacketCount++;
839
840 allowToSend = TRUE;
841 }
842 } while(FALSE);
843
844 if (allowToSend == TRUE)
845 STASendPacket(pAd, pPacket);
846 else
847 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
848 }
849
850 // Dequeue outgoing frames from TxSwQueue[] and process it
851 RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
852
853}
854
855
856/*
857========================================================================
858Routine Description:
859 This routine is used to do packet parsing and classification for Tx packet
860 to STA device, and it will en-queue packets to our TxSwQueue depends on AC
861 class.
862
863Arguments:
864 pAd Pointer to our adapter
865 pPacket Pointer to send packet
866
867Return Value:
868 NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
869 NDIS_STATUS_FAILURE If failed to do en-queue.
870
871Note:
872 You only can put OS-indepened & STA related code in here.
873========================================================================
874*/
875NDIS_STATUS STASendPacket(
876 IN PRTMP_ADAPTER pAd,
877 IN PNDIS_PACKET pPacket)
878{
879 PACKET_INFO PacketInfo;
880 PUCHAR pSrcBufVA;
881 UINT SrcBufLen;
882 UINT AllowFragSize;
883 UCHAR NumberOfFrag;
884 UCHAR QueIdx, UserPriority;
885 MAC_TABLE_ENTRY *pEntry = NULL;
886 unsigned int IrqFlags;
887 UCHAR FlgIsIP = 0;
888 UCHAR Rate;
889
890 // Prepare packet information structure for buffer descriptor
891 // chained within a single NDIS packet.
892 RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
893
894 if (pSrcBufVA == NULL)
895 {
896 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
897 // Resourece is low, system did not allocate virtual address
898 // return NDIS_STATUS_FAILURE directly to upper layer
899 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
900 return NDIS_STATUS_FAILURE;
901 }
902
903
904 if (SrcBufLen < 14)
905 {
906 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
907 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
908 return (NDIS_STATUS_FAILURE);
909 }
910
911 // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
912 // Note multicast packets in adhoc also use BSSID_WCID index.
913 {
914 if(INFRA_ON(pAd))
915 {
916 {
917 pEntry = &pAd->MacTab.Content[BSSID_WCID];
918 RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
919 Rate = pAd->CommonCfg.TxRate;
920 }
921 }
922 else if (ADHOC_ON(pAd))
923 {
924 if (*pSrcBufVA & 0x01)
925 {
926 RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
927 pEntry = &pAd->MacTab.Content[MCAST_WCID];
928 }
929 else
930 {
931 pEntry = MacTableLookup(pAd, pSrcBufVA);
932 }
933 Rate = pAd->CommonCfg.TxRate;
934 }
935 }
936
937 if (!pEntry)
938 {
939 DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
940 // Resourece is low, system did not allocate virtual address
941 // return NDIS_STATUS_FAILURE directly to upper layer
942 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
943 return NDIS_STATUS_FAILURE;
944 }
945
946 if (ADHOC_ON(pAd)
947 )
948 {
949 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
950 }
951
952 //
953 // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
954 // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
955 RTMPCheckEtherType(pAd, pPacket);
956
957
958
959 //
960 // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
961 //
962 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
963 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
964 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
965 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
966 || (pAd->StaCfg.IEEE8021X == TRUE)
967 )
968 && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
969 && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
970 )
971 {
972 DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
973 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
974
975 return (NDIS_STATUS_FAILURE);
976 }
977
978
979 // STEP 1. Decide number of fragments required to deliver this MSDU.
980 // The estimation here is not very accurate because difficult to
981 // take encryption overhead into consideration here. The result
982 // "NumberOfFrag" is then just used to pre-check if enough free
983 // TXD are available to hold this MSDU.
984
985
986 if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
987 NumberOfFrag = 1;
988 else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
989 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
990 else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
991 NumberOfFrag = 1; // Aggregation overwhelms fragmentation
992 else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
993 NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
994 else
995 {
996 // The calculated "NumberOfFrag" is a rough estimation because of various
997 // encryption/encapsulation overhead not taken into consideration. This number is just
998 // used to make sure enough free TXD are available before fragmentation takes place.
999 // In case the actual required number of fragments of an NDIS packet
1000 // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
1001 // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
1002 // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
1003 // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
1004
1005 AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
1006 NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
1007 // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
1008 if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
1009 {
1010 NumberOfFrag--;
1011 }
1012 }
1013
1014 // Save fragment number to Ndis packet reserved field
1015 RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
1016
1017
1018 // STEP 2. Check the requirement of RTS:
1019 // If multiple fragment required, RTS is required only for the first fragment
1020 // if the fragment size large than RTS threshold
1021 // For RT28xx, Let ASIC send RTS/CTS
1022 RTMP_SET_PACKET_RTS(pPacket, 0);
1023 RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
1024
1025 //
1026 // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
1027 //
1028 UserPriority = 0;
1029 QueIdx = QID_AC_BE;
1030 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1031 CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
1032 {
1033 USHORT Protocol;
1034 UCHAR LlcSnapLen = 0, Byte0, Byte1;
1035 do
1036 {
1037 // get Ethernet protocol field
1038 Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
1039 if (Protocol <= 1500)
1040 {
1041 // get Ethernet protocol field from LLC/SNAP
1042 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1043 break;
1044
1045 Protocol = (USHORT)((Byte0 << 8) + Byte1);
1046 LlcSnapLen = 8;
1047 }
1048
1049 // always AC_BE for non-IP packet
1050 if (Protocol != 0x0800)
1051 break;
1052
1053 // get IP header
1054 if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
1055 break;
1056
1057 // return AC_BE if packet is not IPv4
1058 if ((Byte0 & 0xf0) != 0x40)
1059 break;
1060
1061 FlgIsIP = 1;
1062 UserPriority = (Byte1 & 0xe0) >> 5;
1063 QueIdx = MapUserPriorityToAccessCategory[UserPriority];
1064
1065 // TODO: have to check ACM bit. apply TSPEC if ACM is ON
1066 // TODO: downgrade UP & QueIdx before passing ACM
1067 if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
1068 {
1069 UserPriority = 0;
1070 QueIdx = QID_AC_BE;
1071 }
1072 } while (FALSE);
1073 }
1074
1075 RTMP_SET_PACKET_UP(pPacket, UserPriority);
1076
1077
1078
1079 // Make sure SendTxWait queue resource won't be used by other threads
1080 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
1081 if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
1082 {
1083 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1084 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
1085
1086 return NDIS_STATUS_FAILURE;
1087 }
1088 else
1089 {
1090 InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
1091 }
1092 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
1093
1094 if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
1095 IS_HT_STA(pEntry))
1096 {
1097 if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
1098 ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
1099 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
1100 // For IOT compatibility, if
1101 // 1. It is Ralink chip or
1102 // 2. It is OPEN or AES mode,
1103 // then BA session can be bulit.
1104 && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
1105 (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
1106 )
1107 {
1108 BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
1109 }
1110 }
1111
1112 pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
1113 return NDIS_STATUS_SUCCESS;
1114}
1115
1116
1117/*
1118 ========================================================================
1119
1120 Routine Description:
1121 This subroutine will scan through releative ring descriptor to find
1122 out avaliable free ring descriptor and compare with request size.
1123
1124 Arguments:
1125 pAd Pointer to our adapter
1126 QueIdx Selected TX Ring
1127
1128 Return Value:
1129 NDIS_STATUS_FAILURE Not enough free descriptor
1130 NDIS_STATUS_SUCCESS Enough free descriptor
1131
1132 IRQL = PASSIVE_LEVEL
1133 IRQL = DISPATCH_LEVEL
1134
1135 Note:
1136
1137 ========================================================================
1138*/
1139
1140#ifdef RT2870
1141/*
1142 Actually, this function used to check if the TxHardware Queue still has frame need to send.
1143 If no frame need to send, go to sleep, else, still wake up.
1144*/
1145NDIS_STATUS RTMPFreeTXDRequest(
1146 IN PRTMP_ADAPTER pAd,
1147 IN UCHAR QueIdx,
1148 IN UCHAR NumberRequired,
1149 IN PUCHAR FreeNumberIs)
1150{
1151 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
1152 unsigned long IrqFlags;
1153 HT_TX_CONTEXT *pHTTXContext;
1154
1155 switch (QueIdx)
1156 {
1157 case QID_AC_BK:
1158 case QID_AC_BE:
1159 case QID_AC_VI:
1160 case QID_AC_VO:
1161 case QID_HCCA:
1162 {
1163 pHTTXContext = &pAd->TxContext[QueIdx];
1164 RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1165 if ((pHTTXContext->CurWritePosition != pHTTXContext->ENextBulkOutPosition) ||
1166 (pHTTXContext->IRPPending == TRUE))
1167 {
1168 Status = NDIS_STATUS_FAILURE;
1169 }
1170 else
1171 {
1172 Status = NDIS_STATUS_SUCCESS;
1173 }
1174 RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
1175 }
1176 break;
1177
1178 case QID_MGMT:
1179 if (pAd->MgmtRing.TxSwFreeIdx != MGMT_RING_SIZE)
1180 Status = NDIS_STATUS_FAILURE;
1181 else
1182 Status = NDIS_STATUS_SUCCESS;
1183 break;
1184
1185 default:
1186 DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
1187 break;
1188 }
1189
1190 return (Status);
1191
1192}
1193#endif // RT2870 //
1194
1195
1196VOID RTMPSendDisassociationFrame(
1197 IN PRTMP_ADAPTER pAd)
1198{
1199}
1200
1201VOID RTMPSendNullFrame(
1202 IN PRTMP_ADAPTER pAd,
1203 IN UCHAR TxRate,
1204 IN BOOLEAN bQosNull)
1205{
1206 UCHAR NullFrame[48];
1207 ULONG Length;
1208 PHEADER_802_11 pHeader_802_11;
1209
1210 // WPA 802.1x secured port control
1211 if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
1212 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
1213 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
1214 (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1215 || (pAd->StaCfg.IEEE8021X == TRUE)
1216 ) &&
1217 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1218 {
1219 return;
1220 }
1221
1222 NdisZeroMemory(NullFrame, 48);
1223 Length = sizeof(HEADER_802_11);
1224
1225 pHeader_802_11 = (PHEADER_802_11) NullFrame;
1226
1227 pHeader_802_11->FC.Type = BTYPE_DATA;
1228 pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
1229 pHeader_802_11->FC.ToDs = 1;
1230 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1231 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1232 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1233
1234 if (pAd->CommonCfg.bAPSDForcePowerSave)
1235 {
1236 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1237 }
1238 else
1239 {
1240 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
1241 }
1242 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
1243
1244 pAd->Sequence++;
1245 pHeader_802_11->Sequence = pAd->Sequence;
1246
1247 // Prepare QosNull function frame
1248 if (bQosNull)
1249 {
1250 pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
1251
1252 // copy QOS control bytes
1253 NullFrame[Length] = 0;
1254 NullFrame[Length+1] = 0;
1255 Length += 2;// if pad with 2 bytes for alignment, APSD will fail
1256 }
1257
1258 HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
1259
1260}
1261
1262// IRQL = DISPATCH_LEVEL
1263VOID RTMPSendRTSFrame(
1264 IN PRTMP_ADAPTER pAd,
1265 IN PUCHAR pDA,
1266 IN unsigned int NextMpduSize,
1267 IN UCHAR TxRate,
1268 IN UCHAR RTSRate,
1269 IN USHORT AckDuration,
1270 IN UCHAR QueIdx,
1271 IN UCHAR FrameGap)
1272{
1273}
1274
1275
1276
1277// --------------------------------------------------------
1278// FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
1279// Find the WPA key, either Group or Pairwise Key
1280// LEAP + TKIP also use WPA key.
1281// --------------------------------------------------------
1282// Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
1283// In Cisco CCX 2.0 Leap Authentication
1284// WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
1285// Instead of the SharedKey, SharedKey Length may be Zero.
1286VOID STAFindCipherAlgorithm(
1287 IN PRTMP_ADAPTER pAd,
1288 IN TX_BLK *pTxBlk)
1289{
1290 NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
1291 UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
1292 UCHAR KeyIdx = 0xff;
1293 PUCHAR pSrcBufVA;
1294 PCIPHER_KEY pKey = NULL;
1295
1296 pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
1297
1298 {
1299 // Select Cipher
1300 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
1301 Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
1302 else
1303 Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
1304
1305 if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
1306 {
1307 ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
1308
1309 // 4-way handshaking frame must be clear
1310 if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
1311 (pAd->SharedKey[BSS0][0].KeyLen))
1312 {
1313 CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1314 KeyIdx = 0;
1315 }
1316 }
1317 else if (Cipher == Ndis802_11Encryption1Enabled)
1318 {
1319 KeyIdx = pAd->StaCfg.DefaultKeyId;
1320 }
1321 else if ((Cipher == Ndis802_11Encryption2Enabled) ||
1322 (Cipher == Ndis802_11Encryption3Enabled))
1323 {
1324 if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
1325 KeyIdx = pAd->StaCfg.DefaultKeyId;
1326 else if (pAd->SharedKey[BSS0][0].KeyLen)
1327 KeyIdx = 0;
1328 else
1329 KeyIdx = pAd->StaCfg.DefaultKeyId;
1330 }
1331
1332 if (KeyIdx == 0xff)
1333 CipherAlg = CIPHER_NONE;
1334 else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
1335 CipherAlg = CIPHER_NONE;
1336 else if ( pAd->StaCfg.WpaSupplicantUP &&
1337 (Cipher == Ndis802_11Encryption1Enabled) &&
1338 (pAd->StaCfg.IEEE8021X == TRUE) &&
1339 (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
1340 CipherAlg = CIPHER_NONE;
1341 else
1342 {
1343 //Header_802_11.FC.Wep = 1;
1344 CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
1345 pKey = &pAd->SharedKey[BSS0][KeyIdx];
1346 }
1347 }
1348
1349 pTxBlk->CipherAlg = CipherAlg;
1350 pTxBlk->pKey = pKey;
1351}
1352
1353
1354VOID STABuildCommon802_11Header(
1355 IN PRTMP_ADAPTER pAd,
1356 IN TX_BLK *pTxBlk)
1357{
1358 HEADER_802_11 *pHeader_802_11;
1359
1360 //
1361 // MAKE A COMMON 802.11 HEADER
1362 //
1363
1364 // normal wlan header size : 24 octets
1365 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1366
1367 pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1368
1369 NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
1370
1371 pHeader_802_11->FC.FrDs = 0;
1372 pHeader_802_11->FC.Type = BTYPE_DATA;
1373 pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
1374
1375 if (pTxBlk->pMacEntry)
1376 {
1377 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
1378 {
1379 pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
1380 pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
1381 }
1382 else
1383 {
1384 pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
1385 pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1386 }
1387 }
1388 else
1389 {
1390 pHeader_802_11->Sequence = pAd->Sequence;
1391 pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
1392 }
1393
1394 pHeader_802_11->Frag = 0;
1395
1396 pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1397
1398 {
1399 if (INFRA_ON(pAd))
1400 {
1401 {
1402 COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
1403 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1404 COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
1405 pHeader_802_11->FC.ToDs = 1;
1406 }
1407 }
1408 else if (ADHOC_ON(pAd))
1409 {
1410 COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
1411 COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
1412 COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
1413 pHeader_802_11->FC.ToDs = 0;
1414 }
1415 }
1416
1417 if (pTxBlk->CipherAlg != CIPHER_NONE)
1418 pHeader_802_11->FC.Wep = 1;
1419
1420 // -----------------------------------------------------------------
1421 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1422 // -----------------------------------------------------------------
1423 if (pAd->CommonCfg.bAPSDForcePowerSave)
1424 pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
1425 else
1426 pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1427}
1428
1429VOID STABuildCache802_11Header(
1430 IN RTMP_ADAPTER *pAd,
1431 IN TX_BLK *pTxBlk,
1432 IN UCHAR *pHeader)
1433{
1434 MAC_TABLE_ENTRY *pMacEntry;
1435 PHEADER_802_11 pHeader80211;
1436
1437 pHeader80211 = (PHEADER_802_11)pHeader;
1438 pMacEntry = pTxBlk->pMacEntry;
1439
1440 //
1441 // Update the cached 802.11 HEADER
1442 //
1443
1444 // normal wlan header size : 24 octets
1445 pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
1446
1447 // More Bit
1448 pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
1449
1450 // Sequence
1451 pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
1452 pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
1453
1454 {
1455 // The addr3 of normal packet send from DS is Dest Mac address.
1456 if (ADHOC_ON(pAd))
1457 COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
1458 else
1459 COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
1460 }
1461
1462 // -----------------------------------------------------------------
1463 // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
1464 // -----------------------------------------------------------------
1465 if (pAd->CommonCfg.bAPSDForcePowerSave)
1466 pHeader80211->FC.PwrMgmt = PWR_SAVE;
1467 else
1468 pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
1469}
1470
1471static inline PUCHAR STA_Build_ARalink_Frame_Header(
1472 IN RTMP_ADAPTER *pAd,
1473 IN TX_BLK *pTxBlk)
1474{
1475 PUCHAR pHeaderBufPtr;
1476 HEADER_802_11 *pHeader_802_11;
1477 PNDIS_PACKET pNextPacket;
1478 UINT32 nextBufLen;
1479 PQUEUE_ENTRY pQEntry;
1480
1481 STAFindCipherAlgorithm(pAd, pTxBlk);
1482 STABuildCommon802_11Header(pAd, pTxBlk);
1483
1484
1485 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1486 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1487
1488 // steal "order" bit to mark "aggregation"
1489 pHeader_802_11->FC.Order = 1;
1490
1491 // skip common header
1492 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1493
1494 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1495 {
1496 //
1497 // build QOS Control bytes
1498 //
1499 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1500
1501 *(pHeaderBufPtr+1) = 0;
1502 pHeaderBufPtr +=2;
1503 pTxBlk->MpduHeaderLen += 2;
1504 }
1505
1506 // padding at front of LLC header. LLC header should at 4-bytes aligment.
1507 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1508 pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
1509 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1510
1511 // For RA Aggregation,
1512 // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
1513 pQEntry = pTxBlk->TxPacketList.Head;
1514 pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
1515 nextBufLen = GET_OS_PKT_LEN(pNextPacket);
1516 if (RTMP_GET_PACKET_VLAN(pNextPacket))
1517 nextBufLen -= LENGTH_802_1Q;
1518
1519 *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
1520 *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
1521
1522 pHeaderBufPtr += 2;
1523 pTxBlk->MpduHeaderLen += 2;
1524
1525 return pHeaderBufPtr;
1526
1527}
1528
1529static inline PUCHAR STA_Build_AMSDU_Frame_Header(
1530 IN RTMP_ADAPTER *pAd,
1531 IN TX_BLK *pTxBlk)
1532{
1533 PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
1534 HEADER_802_11 *pHeader_802_11;
1535
1536
1537 STAFindCipherAlgorithm(pAd, pTxBlk);
1538 STABuildCommon802_11Header(pAd, pTxBlk);
1539
1540 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1541 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1542
1543 // skip common header
1544 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1545
1546 //
1547 // build QOS Control bytes
1548 //
1549 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1550
1551 //
1552 // A-MSDU packet
1553 //
1554 *pHeaderBufPtr |= 0x80;
1555
1556 *(pHeaderBufPtr+1) = 0;
1557 pHeaderBufPtr +=2;
1558 pTxBlk->MpduHeaderLen += 2;
1559
1560 //pSaveBufPtr = pHeaderBufPtr;
1561
1562 //
1563 // padding at front of LLC header
1564 // LLC header should locate at 4-octets aligment
1565 //
1566 // @@@ MpduHeaderLen excluding padding @@@
1567 //
1568 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1569 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1570 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1571
1572 return pHeaderBufPtr;
1573
1574}
1575
1576
1577VOID STA_AMPDU_Frame_Tx(
1578 IN PRTMP_ADAPTER pAd,
1579 IN TX_BLK *pTxBlk)
1580{
1581 HEADER_802_11 *pHeader_802_11;
1582 PUCHAR pHeaderBufPtr;
1583 USHORT FreeNumber;
1584 MAC_TABLE_ENTRY *pMacEntry;
1585 BOOLEAN bVLANPkt;
1586 PQUEUE_ENTRY pQEntry;
1587
1588 ASSERT(pTxBlk);
1589
1590 while(pTxBlk->TxPacketList.Head)
1591 {
1592 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1593 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1594 if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1595 {
1596 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1597 continue;
1598 }
1599
1600 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1601
1602 pMacEntry = pTxBlk->pMacEntry;
1603 if (pMacEntry->isCached)
1604 {
1605 // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
1606 NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
1607 pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
1608 STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
1609 }
1610 else
1611 {
1612 STAFindCipherAlgorithm(pAd, pTxBlk);
1613 STABuildCommon802_11Header(pAd, pTxBlk);
1614
1615 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1616 }
1617
1618
1619 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1620
1621 // skip common header
1622 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1623
1624 //
1625 // build QOS Control bytes
1626 //
1627 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1628 *(pHeaderBufPtr+1) = 0;
1629 pHeaderBufPtr +=2;
1630 pTxBlk->MpduHeaderLen += 2;
1631
1632 //
1633 // build HTC+
1634 // HTC control filed following QoS field
1635 //
1636 if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
1637 {
1638 if (pMacEntry->isCached == FALSE)
1639 {
1640 // mark HTC bit
1641 pHeader_802_11->FC.Order = 1;
1642
1643 NdisZeroMemory(pHeaderBufPtr, 4);
1644 *(pHeaderBufPtr+3) |= 0x80;
1645 }
1646 pHeaderBufPtr += 4;
1647 pTxBlk->MpduHeaderLen += 4;
1648 }
1649
1650 //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
1651 ASSERT(pTxBlk->MpduHeaderLen >= 24);
1652
1653 // skip 802.3 header
1654 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1655 pTxBlk->SrcBufLen -= LENGTH_802_3;
1656
1657 // skip vlan tag
1658 if (bVLANPkt)
1659 {
1660 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1661 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1662 }
1663
1664 //
1665 // padding at front of LLC header
1666 // LLC header should locate at 4-octets aligment
1667 //
1668 // @@@ MpduHeaderLen excluding padding @@@
1669 //
1670 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1671 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1672 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1673
1674 {
1675
1676 //
1677 // Insert LLC-SNAP encapsulation - 8 octets
1678 //
1679 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1680 if (pTxBlk->pExtraLlcSnapEncap)
1681 {
1682 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1683 pHeaderBufPtr += 6;
1684 // get 2 octets (TypeofLen)
1685 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1686 pHeaderBufPtr += 2;
1687 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1688 }
1689
1690 }
1691
1692 if (pMacEntry->isCached)
1693 {
1694 RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1695 }
1696 else
1697 {
1698 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1699
1700 NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
1701 NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
1702 pMacEntry->isCached = TRUE;
1703 }
1704
1705 // calculate Transmitted AMPDU count and ByteCount
1706 {
1707 pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
1708 pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
1709 }
1710
1711 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1712
1713 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1714
1715 //
1716 // Kick out Tx
1717 //
1718 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1719
1720 pAd->RalinkCounters.KickTxCount++;
1721 pAd->RalinkCounters.OneSecTxDoneCount++;
1722 }
1723
1724}
1725
1726
1727VOID STA_AMSDU_Frame_Tx(
1728 IN PRTMP_ADAPTER pAd,
1729 IN TX_BLK *pTxBlk)
1730{
1731 PUCHAR pHeaderBufPtr;
1732 USHORT FreeNumber;
1733 USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
1734 USHORT totalMPDUSize=0;
1735 UCHAR *subFrameHeader;
1736 UCHAR padding = 0;
1737 USHORT FirstTx = 0, LastTxIdx = 0;
1738 BOOLEAN bVLANPkt;
1739 int frameNum = 0;
1740 PQUEUE_ENTRY pQEntry;
1741
1742
1743 ASSERT(pTxBlk);
1744
1745 ASSERT((pTxBlk->TxPacketList.Number > 1));
1746
1747 while(pTxBlk->TxPacketList.Head)
1748 {
1749 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1750 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1751 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1752 {
1753 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1754 continue;
1755 }
1756
1757 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1758
1759 // skip 802.3 header
1760 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1761 pTxBlk->SrcBufLen -= LENGTH_802_3;
1762
1763 // skip vlan tag
1764 if (bVLANPkt)
1765 {
1766 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1767 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1768 }
1769
1770 if (frameNum == 0)
1771 {
1772 pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
1773
1774 // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
1775 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1776 }
1777 else
1778 {
1779 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
1780 padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
1781 NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
1782 pHeaderBufPtr += padding;
1783 pTxBlk->MpduHeaderLen = padding;
1784 }
1785
1786 //
1787 // A-MSDU subframe
1788 // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
1789 //
1790 subFrameHeader = pHeaderBufPtr;
1791 subFramePayloadLen = pTxBlk->SrcBufLen;
1792
1793 NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
1794
1795
1796 pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
1797 pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
1798
1799
1800 //
1801 // Insert LLC-SNAP encapsulation - 8 octets
1802 //
1803 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
1804
1805 subFramePayloadLen = pTxBlk->SrcBufLen;
1806
1807 if (pTxBlk->pExtraLlcSnapEncap)
1808 {
1809 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1810 pHeaderBufPtr += 6;
1811 // get 2 octets (TypeofLen)
1812 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
1813 pHeaderBufPtr += 2;
1814 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1815 subFramePayloadLen += LENGTH_802_1_H;
1816 }
1817
1818 // update subFrame Length field
1819 subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
1820 subFrameHeader[13] = subFramePayloadLen & 0xFF;
1821
1822 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
1823
1824 if (frameNum ==0)
1825 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1826 else
1827 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
1828
1829 frameNum++;
1830
1831 pAd->RalinkCounters.KickTxCount++;
1832 pAd->RalinkCounters.OneSecTxDoneCount++;
1833
1834 // calculate Transmitted AMSDU Count and ByteCount
1835 {
1836 pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
1837 pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
1838 }
1839
1840 }
1841
1842 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
1843 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
1844
1845 //
1846 // Kick out Tx
1847 //
1848 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1849}
1850
1851VOID STA_Legacy_Frame_Tx(
1852 IN PRTMP_ADAPTER pAd,
1853 IN TX_BLK *pTxBlk)
1854{
1855 HEADER_802_11 *pHeader_802_11;
1856 PUCHAR pHeaderBufPtr;
1857 USHORT FreeNumber;
1858 BOOLEAN bVLANPkt;
1859 PQUEUE_ENTRY pQEntry;
1860
1861 ASSERT(pTxBlk);
1862
1863
1864 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1865 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1866 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1867 {
1868 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1869 return;
1870 }
1871
1872 if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
1873 {
1874 INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
1875 }
1876
1877 if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
1878 TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
1879 else
1880 TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
1881
1882 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
1883
1884 if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
1885 pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
1886
1887 STAFindCipherAlgorithm(pAd, pTxBlk);
1888 STABuildCommon802_11Header(pAd, pTxBlk);
1889
1890
1891 // skip 802.3 header
1892 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
1893 pTxBlk->SrcBufLen -= LENGTH_802_3;
1894
1895 // skip vlan tag
1896 if (bVLANPkt)
1897 {
1898 pTxBlk->pSrcBufData += LENGTH_802_1Q;
1899 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
1900 }
1901
1902 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
1903 pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
1904
1905 // skip common header
1906 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
1907
1908 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
1909 {
1910 //
1911 // build QOS Control bytes
1912 //
1913 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
1914 *(pHeaderBufPtr+1) = 0;
1915 pHeaderBufPtr +=2;
1916 pTxBlk->MpduHeaderLen += 2;
1917 }
1918
1919 // The remaining content of MPDU header should locate at 4-octets aligment
1920 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
1921 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
1922 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
1923
1924 {
1925
1926 //
1927 // Insert LLC-SNAP encapsulation - 8 octets
1928 //
1929 //
1930 // if original Ethernet frame contains no LLC/SNAP,
1931 // then an extra LLC/SNAP encap is required
1932 //
1933 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
1934 if (pTxBlk->pExtraLlcSnapEncap)
1935 {
1936 UCHAR vlan_size;
1937
1938 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
1939 pHeaderBufPtr += 6;
1940 // skip vlan tag
1941 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
1942 // get 2 octets (TypeofLen)
1943 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
1944 pHeaderBufPtr += 2;
1945 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
1946 }
1947
1948 }
1949
1950 //
1951 // prepare for TXWI
1952 // use Wcid as Key Index
1953 //
1954
1955 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
1956
1957 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
1958
1959 HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
1960
1961 pAd->RalinkCounters.KickTxCount++;
1962 pAd->RalinkCounters.OneSecTxDoneCount++;
1963
1964 //
1965 // Kick out Tx
1966 //
1967 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
1968}
1969
1970
1971VOID STA_ARalink_Frame_Tx(
1972 IN PRTMP_ADAPTER pAd,
1973 IN TX_BLK *pTxBlk)
1974{
1975 PUCHAR pHeaderBufPtr;
1976 USHORT FreeNumber;
1977 USHORT totalMPDUSize=0;
1978 USHORT FirstTx, LastTxIdx;
1979 int frameNum = 0;
1980 BOOLEAN bVLANPkt;
1981 PQUEUE_ENTRY pQEntry;
1982
1983
1984 ASSERT(pTxBlk);
1985
1986 ASSERT((pTxBlk->TxPacketList.Number== 2));
1987
1988
1989 FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
1990 while(pTxBlk->TxPacketList.Head)
1991 {
1992 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
1993 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
1994
1995 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
1996 {
1997 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
1998 continue;
1999 }
2000
2001 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2002
2003 // skip 802.3 header
2004 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2005 pTxBlk->SrcBufLen -= LENGTH_802_3;
2006
2007 // skip vlan tag
2008 if (bVLANPkt)
2009 {
2010 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2011 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2012 }
2013
2014 if (frameNum == 0)
2015 { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
2016
2017 pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
2018
2019 // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
2020 // will be updated after final frame was handled.
2021 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2022
2023
2024 //
2025 // Insert LLC-SNAP encapsulation - 8 octets
2026 //
2027 EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
2028
2029 if (pTxBlk->pExtraLlcSnapEncap)
2030 {
2031 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2032 pHeaderBufPtr += 6;
2033 // get 2 octets (TypeofLen)
2034 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2035 pHeaderBufPtr += 2;
2036 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2037 }
2038 }
2039 else
2040 { // For second aggregated frame, we need create the 802.3 header to headerBuf, because PCI will copy it to SDPtr0.
2041
2042 pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
2043 pTxBlk->MpduHeaderLen = 0;
2044
2045 // A-Ralink sub-sequent frame header is the same as 802.3 header.
2046 // DA(6)+SA(6)+FrameType(2)
2047 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader, 12);
2048 pHeaderBufPtr += 12;
2049 // get 2 octets (TypeofLen)
2050 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
2051 pHeaderBufPtr += 2;
2052 pTxBlk->MpduHeaderLen = LENGTH_ARALINK_SUBFRAMEHEAD;
2053 }
2054
2055 totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
2056
2057 //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
2058 if (frameNum ==0)
2059 FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2060 else
2061 LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
2062
2063 frameNum++;
2064
2065 pAd->RalinkCounters.OneSecTxAggregationCount++;
2066 pAd->RalinkCounters.KickTxCount++;
2067 pAd->RalinkCounters.OneSecTxDoneCount++;
2068
2069 }
2070
2071 HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
2072 HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
2073
2074 //
2075 // Kick out Tx
2076 //
2077 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2078
2079}
2080
2081
2082VOID STA_Fragment_Frame_Tx(
2083 IN RTMP_ADAPTER *pAd,
2084 IN TX_BLK *pTxBlk)
2085{
2086 HEADER_802_11 *pHeader_802_11;
2087 PUCHAR pHeaderBufPtr;
2088 USHORT FreeNumber;
2089 UCHAR fragNum = 0;
2090 PACKET_INFO PacketInfo;
2091 USHORT EncryptionOverhead = 0;
2092 UINT32 FreeMpduSize, SrcRemainingBytes;
2093 USHORT AckDuration;
2094 UINT NextMpduSize;
2095 BOOLEAN bVLANPkt;
2096 PQUEUE_ENTRY pQEntry;
2097
2098
2099 ASSERT(pTxBlk);
2100
2101 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2102 pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2103 if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
2104 {
2105 RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
2106 return;
2107 }
2108
2109 ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag));
2110 bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
2111
2112 STAFindCipherAlgorithm(pAd, pTxBlk);
2113 STABuildCommon802_11Header(pAd, pTxBlk);
2114
2115 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2116 {
2117 pTxBlk->pPacket = duplicate_pkt_with_TKIP_MIC(pAd, pTxBlk->pPacket);
2118 if (pTxBlk->pPacket == NULL)
2119 return;
2120 RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
2121 }
2122
2123 // skip 802.3 header
2124 pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
2125 pTxBlk->SrcBufLen -= LENGTH_802_3;
2126
2127
2128 // skip vlan tag
2129 if (bVLANPkt)
2130 {
2131 pTxBlk->pSrcBufData += LENGTH_802_1Q;
2132 pTxBlk->SrcBufLen -= LENGTH_802_1Q;
2133 }
2134
2135 pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
2136 pHeader_802_11 = (HEADER_802_11 *)pHeaderBufPtr;
2137
2138
2139 // skip common header
2140 pHeaderBufPtr += pTxBlk->MpduHeaderLen;
2141
2142 if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
2143 {
2144 //
2145 // build QOS Control bytes
2146 //
2147 *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
2148
2149 *(pHeaderBufPtr+1) = 0;
2150 pHeaderBufPtr +=2;
2151 pTxBlk->MpduHeaderLen += 2;
2152 }
2153
2154 //
2155 // padding at front of LLC header
2156 // LLC header should locate at 4-octets aligment
2157 //
2158 pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
2159 pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
2160 pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
2161
2162
2163
2164 //
2165 // Insert LLC-SNAP encapsulation - 8 octets
2166 //
2167 //
2168 // if original Ethernet frame contains no LLC/SNAP,
2169 // then an extra LLC/SNAP encap is required
2170 //
2171 EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
2172 if (pTxBlk->pExtraLlcSnapEncap)
2173 {
2174 UCHAR vlan_size;
2175
2176 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
2177 pHeaderBufPtr += 6;
2178 // skip vlan tag
2179 vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
2180 // get 2 octets (TypeofLen)
2181 NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
2182 pHeaderBufPtr += 2;
2183 pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
2184 }
2185
2186
2187 // If TKIP is used and fragmentation is required. Driver has to
2188 // append TKIP MIC at tail of the scatter buffer
2189 // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC
2190 if (pTxBlk->CipherAlg == CIPHER_TKIP)
2191 {
2192
2193 // NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust
2194 // to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress.
2195 NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8);
2196 //skb_put((RTPKT_TO_OSPKT(pTxBlk->pPacket))->tail, 8);
2197 pTxBlk->SrcBufLen += 8;
2198 pTxBlk->TotalFrameLen += 8;
2199 pTxBlk->CipherAlg = CIPHER_TKIP_NO_MIC;
2200 }
2201
2202 //
2203 // calcuate the overhead bytes that encryption algorithm may add. This
2204 // affects the calculate of "duration" field
2205 //
2206 if ((pTxBlk->CipherAlg == CIPHER_WEP64) || (pTxBlk->CipherAlg == CIPHER_WEP128))
2207 EncryptionOverhead = 8; //WEP: IV[4] + ICV[4];
2208 else if (pTxBlk->CipherAlg == CIPHER_TKIP_NO_MIC)
2209 EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength
2210 else if (pTxBlk->CipherAlg == CIPHER_TKIP)
2211 EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8]
2212 else if (pTxBlk->CipherAlg == CIPHER_AES)
2213 EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8]
2214 else
2215 EncryptionOverhead = 0;
2216
2217 // decide how much time an ACK/CTS frame will consume in the air
2218 AckDuration = RTMPCalcDuration(pAd, pAd->CommonCfg.ExpectedACKRate[pTxBlk->TxRate], 14);
2219
2220 // Init the total payload length of this frame.
2221 SrcRemainingBytes = pTxBlk->SrcBufLen;
2222
2223 pTxBlk->TotalFragNum = 0xff;
2224
2225 do {
2226
2227 FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC;
2228
2229 FreeMpduSize -= pTxBlk->MpduHeaderLen;
2230
2231 if (SrcRemainingBytes <= FreeMpduSize)
2232 { // this is the last or only fragment
2233
2234 pTxBlk->SrcBufLen = SrcRemainingBytes;
2235
2236 pHeader_802_11->FC.MoreFrag = 0;
2237 pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + AckDuration;
2238
2239 // Indicate the lower layer that this's the last fragment.
2240 pTxBlk->TotalFragNum = fragNum;
2241 }
2242 else
2243 { // more fragment is required
2244
2245 pTxBlk->SrcBufLen = FreeMpduSize;
2246
2247 NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), ((UINT)pAd->CommonCfg.FragmentThreshold));
2248 pHeader_802_11->FC.MoreFrag = 1;
2249 pHeader_802_11->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead);
2250 }
2251
2252 if (fragNum == 0)
2253 pTxBlk->FrameGap = IFS_HTTXOP;
2254 else
2255 pTxBlk->FrameGap = IFS_SIFS;
2256
2257 RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
2258
2259 HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &FreeNumber);
2260
2261 pAd->RalinkCounters.KickTxCount++;
2262 pAd->RalinkCounters.OneSecTxDoneCount++;
2263
2264 // Update the frame number, remaining size of the NDIS packet payload.
2265
2266 // space for 802.11 header.
2267 if (fragNum == 0 && pTxBlk->pExtraLlcSnapEncap)
2268 pTxBlk->MpduHeaderLen -= LENGTH_802_1_H;
2269
2270 fragNum++;
2271 SrcRemainingBytes -= pTxBlk->SrcBufLen;
2272 pTxBlk->pSrcBufData += pTxBlk->SrcBufLen;
2273
2274 pHeader_802_11->Frag++; // increase Frag #
2275
2276 }while(SrcRemainingBytes > 0);
2277
2278 //
2279 // Kick out Tx
2280 //
2281 HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
2282}
2283
2284
2285#define RELEASE_FRAMES_OF_TXBLK(_pAd, _pTxBlk, _pQEntry, _Status) \
2286 while(_pTxBlk->TxPacketList.Head) \
2287 { \
2288 _pQEntry = RemoveHeadQueue(&_pTxBlk->TxPacketList); \
2289 RELEASE_NDIS_PACKET(_pAd, QUEUE_ENTRY_TO_PACKET(_pQEntry), _Status); \
2290 }
2291
2292
2293/*
2294 ========================================================================
2295
2296 Routine Description:
2297 Copy frame from waiting queue into relative ring buffer and set
2298 appropriate ASIC register to kick hardware encryption before really
2299 sent out to air.
2300
2301 Arguments:
2302 pAd Pointer to our adapter
2303 PNDIS_PACKET Pointer to outgoing Ndis frame
2304 NumberOfFrag Number of fragment required
2305
2306 Return Value:
2307 None
2308
2309 IRQL = DISPATCH_LEVEL
2310
2311 Note:
2312
2313 ========================================================================
2314*/
2315NDIS_STATUS STAHardTransmit(
2316 IN PRTMP_ADAPTER pAd,
2317 IN TX_BLK *pTxBlk,
2318 IN UCHAR QueIdx)
2319{
2320 NDIS_PACKET *pPacket;
2321 PQUEUE_ENTRY pQEntry;
2322
2323 // ---------------------------------------------
2324 // STEP 0. DO SANITY CHECK AND SOME EARLY PREPARATION.
2325 // ---------------------------------------------
2326 //
2327 ASSERT(pTxBlk->TxPacketList.Number);
2328 if (pTxBlk->TxPacketList.Head == NULL)
2329 {
2330 DBGPRINT(RT_DEBUG_ERROR, ("pTxBlk->TotalFrameNum == %ld!\n", pTxBlk->TxPacketList.Number));
2331 return NDIS_STATUS_FAILURE;
2332 }
2333
2334 pPacket = QUEUE_ENTRY_TO_PACKET(pTxBlk->TxPacketList.Head);
2335
2336 // ------------------------------------------------------------------
2337 // STEP 1. WAKE UP PHY
2338 // outgoing frame always wakeup PHY to prevent frame lost and
2339 // turn off PSM bit to improve performance
2340 // ------------------------------------------------------------------
2341 // not to change PSM bit, just send this frame out?
2342 if ((pAd->StaCfg.Psm == PWR_SAVE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
2343 {
2344 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicForceWakeup At HardTx\n"));
2345 AsicForceWakeup(pAd, TRUE);
2346 }
2347
2348 // It should not change PSM bit, when APSD turn on.
2349 if ((!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable) && (pAd->CommonCfg.bAPSDForcePowerSave == FALSE))
2350 || (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
2351 || (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)))
2352 {
2353 if ((pAd->StaCfg.Psm == PWR_SAVE) &&
2354 (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeFast_PSP))
2355 MlmeSetPsmBit(pAd, PWR_ACTIVE);
2356 }
2357
2358 switch (pTxBlk->TxFrameType)
2359 {
2360 case TX_AMPDU_FRAME:
2361 STA_AMPDU_Frame_Tx(pAd, pTxBlk);
2362 break;
2363 case TX_AMSDU_FRAME:
2364 STA_AMSDU_Frame_Tx(pAd, pTxBlk);
2365 break;
2366 case TX_LEGACY_FRAME:
2367 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2368 break;
2369 case TX_MCAST_FRAME:
2370 STA_Legacy_Frame_Tx(pAd, pTxBlk);
2371 break;
2372 case TX_RALINK_FRAME:
2373 STA_ARalink_Frame_Tx(pAd, pTxBlk);
2374 break;
2375 case TX_FRAG_FRAME:
2376 STA_Fragment_Frame_Tx(pAd, pTxBlk);
2377 break;
2378 default:
2379 {
2380 // It should not happened!
2381 DBGPRINT(RT_DEBUG_ERROR, ("Send a pacekt was not classified!! It should not happen!\n"));
2382 while(pTxBlk->TxPacketList.Number)
2383 {
2384 pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
2385 pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
2386 if (pPacket)
2387 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2388 }
2389 }
2390 break;
2391 }
2392
2393 return (NDIS_STATUS_SUCCESS);
2394
2395}
2396
2397ULONG HashBytesPolynomial(UCHAR *value, unsigned int len)
2398{
2399 unsigned char *word = value;
2400 unsigned int ret = 0;
2401 unsigned int i;
2402
2403 for(i=0; i < len; i++)
2404 {
2405 int mod = i % 32;
2406 ret ^=(unsigned int) (word[i]) << mod;
2407 ret ^=(unsigned int) (word[i]) >> (32 - mod);
2408 }
2409 return ret;
2410}
2411
2412VOID Sta_Announce_or_Forward_802_3_Packet(
2413 IN PRTMP_ADAPTER pAd,
2414 IN PNDIS_PACKET pPacket,
2415 IN UCHAR FromWhichBSSID)
2416{
2417 if (TRUE
2418 )
2419 {
2420 announce_802_3_packet(pAd, pPacket);
2421 }
2422 else
2423 {
2424 // release packet
2425 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
2426 }
2427}
2428
diff --git a/drivers/staging/rt2870/sta/sanity.c b/drivers/staging/rt2870/sta/sanity.c
index 7d530f601602..f1f2333bb993 100644
--- a/drivers/staging/rt2870/sta/sanity.c
+++ b/drivers/staging/rt2870/sta/sanity.c
@@ -1,418 +1 @@
1/* #include "../../rt2860/sta/sanity.c"
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 sanity.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-09-01 add WMM support
36*/
37#include "../rt_config.h"
38
39extern UCHAR CISCO_OUI[];
40
41extern UCHAR WPA_OUI[];
42extern UCHAR RSN_OUI[];
43extern UCHAR WME_INFO_ELEM[];
44extern UCHAR WME_PARM_ELEM[];
45extern UCHAR Ccx2QosInfo[];
46extern UCHAR RALINK_OUI[];
47extern UCHAR BROADCOM_OUI[];
48
49/*
50 ==========================================================================
51 Description:
52 MLME message sanity check
53 Return:
54 TRUE if all parameters are OK, FALSE otherwise
55 ==========================================================================
56 */
57BOOLEAN MlmeStartReqSanity(
58 IN PRTMP_ADAPTER pAd,
59 IN VOID *Msg,
60 IN ULONG MsgLen,
61 OUT CHAR Ssid[],
62 OUT UCHAR *pSsidLen)
63{
64 MLME_START_REQ_STRUCT *Info;
65
66 Info = (MLME_START_REQ_STRUCT *)(Msg);
67
68 if (Info->SsidLen > MAX_LEN_OF_SSID)
69 {
70 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqSanity fail - wrong SSID length\n"));
71 return FALSE;
72 }
73
74 *pSsidLen = Info->SsidLen;
75 NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen);
76
77 return TRUE;
78}
79
80/*
81 ==========================================================================
82 Description:
83 MLME message sanity check
84 Return:
85 TRUE if all parameters are OK, FALSE otherwise
86
87 IRQL = DISPATCH_LEVEL
88
89 ==========================================================================
90 */
91BOOLEAN PeerAssocRspSanity(
92 IN PRTMP_ADAPTER pAd,
93 IN VOID *pMsg,
94 IN ULONG MsgLen,
95 OUT PUCHAR pAddr2,
96 OUT USHORT *pCapabilityInfo,
97 OUT USHORT *pStatus,
98 OUT USHORT *pAid,
99 OUT UCHAR SupRate[],
100 OUT UCHAR *pSupRateLen,
101 OUT UCHAR ExtRate[],
102 OUT UCHAR *pExtRateLen,
103 OUT HT_CAPABILITY_IE *pHtCapability,
104 OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
105 OUT UCHAR *pHtCapabilityLen,
106 OUT UCHAR *pAddHtInfoLen,
107 OUT UCHAR *pNewExtChannelOffset,
108 OUT PEDCA_PARM pEdcaParm,
109 OUT UCHAR *pCkipFlag)
110{
111 CHAR IeType, *Ptr;
112 PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
113 PEID_STRUCT pEid;
114 ULONG Length = 0;
115
116 *pNewExtChannelOffset = 0xff;
117 *pHtCapabilityLen = 0;
118 *pAddHtInfoLen = 0;
119 COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
120 Ptr = pFrame->Octet;
121 Length += LENGTH_802_11;
122
123 NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2);
124 Length += 2;
125 NdisMoveMemory(pStatus, &pFrame->Octet[2], 2);
126 Length += 2;
127 *pCkipFlag = 0;
128 *pExtRateLen = 0;
129 pEdcaParm->bValid = FALSE;
130
131 if (*pStatus != MLME_SUCCESS)
132 return TRUE;
133
134 NdisMoveMemory(pAid, &pFrame->Octet[4], 2);
135 Length += 2;
136
137 // Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform
138 *pAid = (*pAid) & 0x3fff; // AID is low 14-bit
139
140 // -- get supported rates from payload and advance the pointer
141 IeType = pFrame->Octet[6];
142 *pSupRateLen = pFrame->Octet[7];
143 if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES))
144 {
145 DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity fail - wrong SupportedRates IE\n"));
146 return FALSE;
147 }
148 else
149 NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen);
150
151 Length = Length + 2 + *pSupRateLen;
152
153 // many AP implement proprietary IEs in non-standard order, we'd better
154 // tolerate mis-ordered IEs to get best compatibility
155 pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)];
156
157 // get variable fields from payload and advance the pointer
158 while ((Length + 2 + pEid->Len) <= MsgLen)
159 {
160 switch (pEid->Eid)
161 {
162 case IE_EXT_SUPP_RATES:
163 if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
164 {
165 NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len);
166 *pExtRateLen = pEid->Len;
167 }
168 break;
169
170 case IE_HT_CAP:
171 case IE_HT_CAP2:
172 if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!!
173 {
174 NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE);
175
176 *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
177 *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
178
179 *pHtCapabilityLen = SIZE_HT_CAP_IE;
180 }
181 else
182 {
183 DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_HT_CAP. \n"));
184 }
185
186 break;
187 case IE_ADD_HT:
188 case IE_ADD_HT2:
189 if (pEid->Len >= sizeof(ADD_HT_INFO_IE))
190 {
191 // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only
192 // copy first sizeof(ADD_HT_INFO_IE)
193 NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE));
194
195 *(USHORT *)(&pAddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo2));
196 *(USHORT *)(&pAddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&pAddHtInfo->AddHtInfo3));
197
198 *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE;
199 }
200 else
201 {
202 DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_ADD_HT. \n"));
203 }
204
205 break;
206 case IE_SECONDARY_CH_OFFSET:
207 if (pEid->Len == 1)
208 {
209 *pNewExtChannelOffset = pEid->Octet[0];
210 }
211 else
212 {
213 DBGPRINT(RT_DEBUG_WARN, ("PeerAssocRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n"));
214 }
215 break;
216 case IE_AIRONET_CKIP:
217 // 0. Check Aironet IE length, it must be larger or equal to 28
218 // Cisco's AP VxWork version(will not be supported) used this IE length as 28
219 // Cisco's AP IOS version used this IE length as 30
220 if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2))
221 break;
222
223 // 1. Copy CKIP flag byte to buffer for process
224 *pCkipFlag = *(pEid->Octet + 8);
225 break;
226
227 case IE_AIRONET_IPADDRESS:
228 if (pEid->Len != 0x0A)
229 break;
230
231 // Get Cisco Aironet IP information
232 if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1)
233 NdisMoveMemory(pAd->StaCfg.AironetIPAddress, pEid->Octet + 4, 4);
234 break;
235
236 // CCX2, WMM use the same IE value
237 // case IE_CCX_V2:
238 case IE_VENDOR_SPECIFIC:
239 // handle WME PARAMTER ELEMENT
240 if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24))
241 {
242 PUCHAR ptr;
243 int i;
244
245 // parsing EDCA parameters
246 pEdcaParm->bValid = TRUE;
247 pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10;
248 pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20;
249 pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40;
250 //pEdcaParm->bMoreDataAck = FALSE; // pEid->Octet[0] & 0x80;
251 pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
252 pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0;
253 ptr = &pEid->Octet[8];
254 for (i=0; i<4; i++)
255 {
256 UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX
257 pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM
258 pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN
259 pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin
260 pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax
261 pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us
262 ptr += 4; // point to next AC
263 }
264 }
265
266 // handle CCX IE
267 else
268 {
269 // 0. Check the size and CCX admin control
270 if (pAd->StaCfg.CCXControl.field.Enable == 0)
271 break;
272 if (pEid->Len != 5)
273 break;
274
275 // Turn CCX2 if matched
276 if (NdisEqualMemory(pEid->Octet, Ccx2IeInfo, 5) == 1)
277 pAd->StaCfg.CCXEnable = TRUE;
278 break;
279 }
280 break;
281
282 default:
283 DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspSanity - ignore unrecognized EID = %d\n", pEid->Eid));
284 break;
285 }
286
287 Length = Length + 2 + pEid->Len;
288 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
289 }
290
291 // Force CCX2 enable to TRUE for those AP didn't replay CCX v2 IE, we still force it to be on
292 if (pAd->StaCfg.CCXControl.field.Enable == 1)
293 pAd->StaCfg.CCXEnable = TRUE;
294
295 return TRUE;
296}
297
298/*
299 ==========================================================================
300 Description:
301 MLME message sanity check
302 Return:
303 TRUE if all parameters are OK, FALSE otherwise
304
305 IRQL = DISPATCH_LEVEL
306
307 ==========================================================================
308 */
309BOOLEAN PeerProbeReqSanity(
310 IN PRTMP_ADAPTER pAd,
311 IN VOID *Msg,
312 IN ULONG MsgLen,
313 OUT PUCHAR pAddr2,
314 OUT CHAR Ssid[],
315 OUT UCHAR *pSsidLen)
316{
317 UCHAR Idx;
318 UCHAR RateLen;
319 CHAR IeType;
320 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
321
322 COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
323
324 if ((pFrame->Octet[0] != IE_SSID) || (pFrame->Octet[1] > MAX_LEN_OF_SSID))
325 {
326 DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SSID IE(Type=%d,Len=%d)\n",pFrame->Octet[0],pFrame->Octet[1]));
327 return FALSE;
328 }
329
330 *pSsidLen = pFrame->Octet[1];
331 NdisMoveMemory(Ssid, &pFrame->Octet[2], *pSsidLen);
332
333 Idx = *pSsidLen + 2;
334
335 // -- get supported rates from payload and advance the pointer
336 IeType = pFrame->Octet[Idx];
337 RateLen = pFrame->Octet[Idx + 1];
338 if (IeType != IE_SUPP_RATES)
339 {
340 DBGPRINT(RT_DEBUG_TRACE, ("PeerProbeReqSanity fail - wrong SupportRates IE(Type=%d,Len=%d)\n",pFrame->Octet[Idx],pFrame->Octet[Idx+1]));
341 return FALSE;
342 }
343 else
344 {
345 if ((pAd->CommonCfg.PhyMode == PHY_11G) && (RateLen < 8))
346 return (FALSE);
347 }
348
349 return TRUE;
350}
351
352/*
353 ==========================================================================
354 Description:
355
356 IRQL = DISPATCH_LEVEL
357
358 ==========================================================================
359 */
360BOOLEAN GetTimBit(
361 IN CHAR *Ptr,
362 IN USHORT Aid,
363 OUT UCHAR *TimLen,
364 OUT UCHAR *BcastFlag,
365 OUT UCHAR *DtimCount,
366 OUT UCHAR *DtimPeriod,
367 OUT UCHAR *MessageToMe)
368{
369 UCHAR BitCntl, N1, N2, MyByte, MyBit;
370 CHAR *IdxPtr;
371
372 IdxPtr = Ptr;
373
374 IdxPtr ++;
375 *TimLen = *IdxPtr;
376
377 // get DTIM Count from TIM element
378 IdxPtr ++;
379 *DtimCount = *IdxPtr;
380
381 // get DTIM Period from TIM element
382 IdxPtr++;
383 *DtimPeriod = *IdxPtr;
384
385 // get Bitmap Control from TIM element
386 IdxPtr++;
387 BitCntl = *IdxPtr;
388
389 if ((*DtimCount == 0) && (BitCntl & 0x01))
390 *BcastFlag = TRUE;
391 else
392 *BcastFlag = FALSE;
393
394 // Parse Partial Virtual Bitmap from TIM element
395 N1 = BitCntl & 0xfe; // N1 is the first bitmap byte#
396 N2 = *TimLen - 4 + N1; // N2 is the last bitmap byte#
397
398 if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3)))
399 *MessageToMe = FALSE;
400 else
401 {
402 MyByte = (Aid >> 3) - N1; // my byte position in the bitmap byte-stream
403 MyBit = Aid % 16 - ((MyByte & 0x01)? 8:0);
404
405 IdxPtr += (MyByte + 1);
406
407 //if (*IdxPtr)
408 // DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr));
409
410 if (*IdxPtr & (0x01 << MyBit))
411 *MessageToMe = TRUE;
412 else
413 *MessageToMe = FALSE;
414 }
415
416 return TRUE;
417}
418
diff --git a/drivers/staging/rt2870/sta/sync.c b/drivers/staging/rt2870/sta/sync.c
index da26e0511607..66c8772ad346 100644
--- a/drivers/staging/rt2870/sta/sync.c
+++ b/drivers/staging/rt2870/sta/sync.c
@@ -1,1604 +1 @@
1/* #include "../../rt2860/sta/sync.c"
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 sync.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-09-01 modified for rt2561/2661
36 Jan Lee 2006-08-01 modified for rt2860 for 802.11n
37*/
38#include "../rt_config.h"
39
40#define ADHOC_ENTRY_BEACON_LOST_TIME (2*OS_HZ) // 2 sec
41
42/*
43 ==========================================================================
44 Description:
45 The sync state machine,
46 Parameters:
47 Sm - pointer to the state machine
48 Note:
49 the state machine looks like the following
50
51 ==========================================================================
52 */
53VOID SyncStateMachineInit(
54 IN PRTMP_ADAPTER pAd,
55 IN STATE_MACHINE *Sm,
56 OUT STATE_MACHINE_FUNC Trans[])
57{
58 StateMachineInit(Sm, Trans, MAX_SYNC_STATE, MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, SYNC_IDLE, SYNC_MACHINE_BASE);
59
60 // column 1
61 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)MlmeScanReqAction);
62 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)MlmeJoinReqAction);
63 StateMachineSetAction(Sm, SYNC_IDLE, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)MlmeStartReqAction);
64 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeacon);
65 StateMachineSetAction(Sm, SYNC_IDLE, MT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)PeerProbeReqAction);
66
67 //column 2
68 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
69 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
70 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
71 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtJoinAction);
72 StateMachineSetAction(Sm, JOIN_WAIT_BEACON, MT2_BEACON_TIMEOUT, (STATE_MACHINE_FUNC)BeaconTimeoutAtJoinAction);
73
74 // column 3
75 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenScan);
76 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_JOIN_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenJoin);
77 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_MLME_START_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenStart);
78 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_BEACON, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
79 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)PeerBeaconAtScanAction);
80 StateMachineSetAction(Sm, SCAN_LISTEN, MT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)ScanTimeoutAction);
81
82 // timer init
83 RTMPInitTimer(pAd, &pAd->MlmeAux.BeaconTimer, GET_TIMER_FUNCTION(BeaconTimeout), pAd, FALSE);
84 RTMPInitTimer(pAd, &pAd->MlmeAux.ScanTimer, GET_TIMER_FUNCTION(ScanTimeout), pAd, FALSE);
85}
86
87/*
88 ==========================================================================
89 Description:
90 Beacon timeout handler, executed in timer thread
91
92 IRQL = DISPATCH_LEVEL
93
94 ==========================================================================
95 */
96VOID BeaconTimeout(
97 IN PVOID SystemSpecific1,
98 IN PVOID FunctionContext,
99 IN PVOID SystemSpecific2,
100 IN PVOID SystemSpecific3)
101{
102 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
103
104 DBGPRINT(RT_DEBUG_TRACE,("SYNC - BeaconTimeout\n"));
105
106 // Do nothing if the driver is starting halt state.
107 // This might happen when timer already been fired before cancel timer with mlmehalt
108 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
109 return;
110
111 if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
112 )
113 {
114 UCHAR BBPValue = 0;
115 AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
116 AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
117 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
118 BBPValue &= (~0x18);
119 BBPValue |= 0x10;
120 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
121 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr));
122 }
123
124 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_BEACON_TIMEOUT, 0, NULL);
125 RT28XX_MLME_HANDLER(pAd);
126}
127
128/*
129 ==========================================================================
130 Description:
131 Scan timeout handler, executed in timer thread
132
133 IRQL = DISPATCH_LEVEL
134
135 ==========================================================================
136 */
137VOID ScanTimeout(
138 IN PVOID SystemSpecific1,
139 IN PVOID FunctionContext,
140 IN PVOID SystemSpecific2,
141 IN PVOID SystemSpecific3)
142{
143 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
144
145
146 // Do nothing if the driver is starting halt state.
147 // This might happen when timer already been fired before cancel timer with mlmehalt
148 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
149 return;
150
151 if (MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_SCAN_TIMEOUT, 0, NULL))
152 {
153 RT28XX_MLME_HANDLER(pAd);
154 }
155 else
156 {
157 // To prevent SyncMachine.CurrState is SCAN_LISTEN forever.
158 pAd->MlmeAux.Channel = 0;
159 ScanNextChannel(pAd);
160 if (pAd->CommonCfg.bWirelessEvent)
161 {
162 RTMPSendWirelessEvent(pAd, IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
163 }
164 }
165}
166
167/*
168 ==========================================================================
169 Description:
170 MLME SCAN req state machine procedure
171 ==========================================================================
172 */
173VOID MlmeScanReqAction(
174 IN PRTMP_ADAPTER pAd,
175 IN MLME_QUEUE_ELEM *Elem)
176{
177 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType, BBPValue = 0;
178 BOOLEAN TimerCancelled;
179 ULONG Now;
180 USHORT Status;
181 PHEADER_802_11 pHdr80211;
182 PUCHAR pOutBuffer = NULL;
183 NDIS_STATUS NStatus;
184
185 // Check the total scan tries for one single OID command
186 // If this is the CCX 2.0 Case, skip that!
187 if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
188 {
189 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeScanReqAction before Startup\n"));
190 return;
191 }
192
193 // Increase the scan retry counters.
194 pAd->StaCfg.ScanCnt++;
195
196
197 // first check the parameter sanity
198 if (MlmeScanReqSanity(pAd,
199 Elem->Msg,
200 Elem->MsgLen,
201 &BssType,
202 Ssid,
203 &SsidLen,
204 &ScanType))
205 {
206
207 // Check for channel load and noise hist request
208 // Suspend MSDU only at scan request, not the last two mentioned
209 if ((ScanType == SCAN_CISCO_NOISE) || (ScanType == SCAN_CISCO_CHANNEL_LOAD))
210 {
211 if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
212 RTMPSuspendMsduTransmission(pAd); // Suspend MSDU transmission here
213 }
214 else
215 {
216 // Suspend MSDU transmission here
217 RTMPSuspendMsduTransmission(pAd);
218 }
219
220 //
221 // To prevent data lost.
222 // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress.
223 // And should send an NULL data with turned PSM bit off to AP, when scan progress done
224 //
225 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
226 {
227 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);
228 if (NStatus == NDIS_STATUS_SUCCESS)
229 {
230 pHdr80211 = (PHEADER_802_11) pOutBuffer;
231 MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
232 pHdr80211->Duration = 0;
233 pHdr80211->FC.Type = BTYPE_DATA;
234 pHdr80211->FC.PwrMgmt = PWR_SAVE;
235
236 // Send using priority queue
237 MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
238 DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame for off channel RM\n"));
239 MlmeFreeMemory(pAd, pOutBuffer);
240 RTMPusecDelay(5000);
241 }
242 }
243
244 NdisGetSystemUpTime(&Now);
245 pAd->StaCfg.LastScanTime = Now;
246 // reset all the timers
247 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
248 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
249
250 // record desired BSS parameters
251 pAd->MlmeAux.BssType = BssType;
252 pAd->MlmeAux.ScanType = ScanType;
253 pAd->MlmeAux.SsidLen = SsidLen;
254 NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
255 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
256
257 // start from the first channel
258 pAd->MlmeAux.Channel = FirstChannel(pAd);
259
260 // Change the scan channel when dealing with CCX beacon report
261 if ((ScanType == SCAN_CISCO_PASSIVE) || (ScanType == SCAN_CISCO_ACTIVE) ||
262 (ScanType == SCAN_CISCO_CHANNEL_LOAD) || (ScanType == SCAN_CISCO_NOISE))
263 pAd->MlmeAux.Channel = pAd->StaCfg.CCXScanChannel;
264
265 // Let BBP register at 20MHz to do scan
266 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
267 BBPValue &= (~0x18);
268 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
269 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
270 ScanNextChannel(pAd);
271 }
272 else
273 {
274 DBGPRINT_ERR(("SYNC - MlmeScanReqAction() sanity check fail\n"));
275 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
276 Status = MLME_INVALID_FORMAT;
277 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
278 }
279}
280
281/*
282 ==========================================================================
283 Description:
284 MLME JOIN req state machine procedure
285 ==========================================================================
286 */
287VOID MlmeJoinReqAction(
288 IN PRTMP_ADAPTER pAd,
289 IN MLME_QUEUE_ELEM *Elem)
290{
291 UCHAR BBPValue = 0;
292 BSS_ENTRY *pBss;
293 BOOLEAN TimerCancelled;
294 HEADER_802_11 Hdr80211;
295 NDIS_STATUS NStatus;
296 ULONG FrameLen = 0;
297 PUCHAR pOutBuffer = NULL;
298 PUCHAR pSupRate = NULL;
299 UCHAR SupRateLen;
300 PUCHAR pExtRate = NULL;
301 UCHAR ExtRateLen;
302 UCHAR ASupRate[] = {0x8C, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6C};
303 UCHAR ASupRateLen = sizeof(ASupRate)/sizeof(UCHAR);
304 MLME_JOIN_REQ_STRUCT *pInfo = (MLME_JOIN_REQ_STRUCT *)(Elem->Msg);
305
306 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeJoinReqAction(BSS #%ld)\n", pInfo->BssIdx));
307
308
309 // reset all the timers
310 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
311 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
312
313 pBss = &pAd->MlmeAux.SsidBssTab.BssEntry[pInfo->BssIdx];
314
315 // record the desired SSID & BSSID we're waiting for
316 COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pBss->Bssid);
317
318 // If AP's SSID is not hidden, it is OK for updating ssid to MlmeAux again.
319 if (pBss->Hidden == 0)
320 {
321 NdisMoveMemory(pAd->MlmeAux.Ssid, pBss->Ssid, pBss->SsidLen);
322 pAd->MlmeAux.SsidLen = pBss->SsidLen;
323 }
324
325 pAd->MlmeAux.BssType = pBss->BssType;
326 pAd->MlmeAux.Channel = pBss->Channel;
327 pAd->MlmeAux.CentralChannel = pBss->CentralChannel;
328
329 // Let BBP register at 20MHz to do scan
330 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
331 BBPValue &= (~0x18);
332 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
333 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
334
335 // switch channel and waiting for beacon timer
336 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
337 AsicLockChannel(pAd, pAd->MlmeAux.Channel);
338 RTMPSetTimer(&pAd->MlmeAux.BeaconTimer, JOIN_TIMEOUT);
339
340 do
341 {
342 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
343 (pAd->MlmeAux.Channel > 14) &&
344 RadarChannelCheck(pAd, pAd->MlmeAux.Channel))
345 )
346 {
347 //
348 // We can't send any Probe request frame to meet 802.11h.
349 //
350 if (pBss->Hidden == 0)
351 break;
352 }
353
354 //
355 // send probe request
356 //
357 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
358 if (NStatus == NDIS_STATUS_SUCCESS)
359 {
360 if (pAd->MlmeAux.Channel <= 14)
361 {
362 pSupRate = pAd->CommonCfg.SupRate;
363 SupRateLen = pAd->CommonCfg.SupRateLen;
364 pExtRate = pAd->CommonCfg.ExtRate;
365 ExtRateLen = pAd->CommonCfg.ExtRateLen;
366 }
367 else
368 {
369 //
370 // Overwrite Support Rate, CCK rate are not allowed
371 //
372 pSupRate = ASupRate;
373 SupRateLen = ASupRateLen;
374 ExtRateLen = 0;
375 }
376
377 if (pAd->MlmeAux.BssType == BSS_INFRA)
378 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->MlmeAux.Bssid, pAd->MlmeAux.Bssid);
379 else
380 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
381
382 MakeOutgoingFrame(pOutBuffer, &FrameLen,
383 sizeof(HEADER_802_11), &Hdr80211,
384 1, &SsidIe,
385 1, &pAd->MlmeAux.SsidLen,
386 pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid,
387 1, &SupRateIe,
388 1, &SupRateLen,
389 SupRateLen, pSupRate,
390 END_OF_ARGS);
391
392 if (ExtRateLen)
393 {
394 ULONG Tmp;
395 MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
396 1, &ExtRateIe,
397 1, &ExtRateLen,
398 ExtRateLen, pExtRate,
399 END_OF_ARGS);
400 FrameLen += Tmp;
401 }
402
403
404 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
405 MlmeFreeMemory(pAd, pOutBuffer);
406 }
407 } while (FALSE);
408
409 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Switch to ch %d, Wait BEACON from %02x:%02x:%02x:%02x:%02x:%02x\n",
410 pBss->Channel, pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2], pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
411
412 pAd->Mlme.SyncMachine.CurrState = JOIN_WAIT_BEACON;
413}
414
415/*
416 ==========================================================================
417 Description:
418 MLME START Request state machine procedure, starting an IBSS
419 ==========================================================================
420 */
421VOID MlmeStartReqAction(
422 IN PRTMP_ADAPTER pAd,
423 IN MLME_QUEUE_ELEM *Elem)
424{
425 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen;
426 BOOLEAN TimerCancelled;
427
428 // New for WPA security suites
429 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
430 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
431 LARGE_INTEGER TimeStamp;
432 BOOLEAN Privacy;
433 USHORT Status;
434
435 // Init Variable IE structure
436 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
437 pVIE->Length = 0;
438 TimeStamp.u.LowPart = 0;
439 TimeStamp.u.HighPart = 0;
440
441 if (MlmeStartReqSanity(pAd, Elem->Msg, Elem->MsgLen, Ssid, &SsidLen))
442 {
443 // reset all the timers
444 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &TimerCancelled);
445 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
446
447 //
448 // Start a new IBSS. All IBSS parameters are decided now....
449 //
450 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - Start a new IBSS. All IBSS parameters are decided now.... \n"));
451 pAd->MlmeAux.BssType = BSS_ADHOC;
452 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
453 pAd->MlmeAux.SsidLen = SsidLen;
454
455 // generate a radom number as BSSID
456 MacAddrRandomBssid(pAd, pAd->MlmeAux.Bssid);
457 DBGPRINT(RT_DEBUG_TRACE, ("MlmeStartReqAction - generate a radom number as BSSID \n"));
458
459 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
460 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
461 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
462 pAd->MlmeAux.CapabilityInfo = CAP_GENERATE(0,1,Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 1, 0);
463 pAd->MlmeAux.BeaconPeriod = pAd->CommonCfg.BeaconPeriod;
464 pAd->MlmeAux.AtimWin = pAd->StaCfg.AtimWin;
465 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
466
467 pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
468 pAd->MlmeAux.CentralChannel = pAd->CommonCfg.CentralChannel;
469
470 pAd->MlmeAux.SupRateLen= pAd->CommonCfg.SupRateLen;
471 NdisMoveMemory(pAd->MlmeAux.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
472 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
473 pAd->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen;
474 NdisMoveMemory(pAd->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
475 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
476
477 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
478 {
479 RTMPUpdateHTIE(&pAd->CommonCfg.DesiredHtPhy, &pAd->StaCfg.DesiredHtPhyInfo.MCSSet[0], &pAd->MlmeAux.HtCapability, &pAd->MlmeAux.AddHtInfo);
480 pAd->MlmeAux.HtCapabilityLen = sizeof(HT_CAPABILITY_IE);
481 // Not turn pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE here.
482 DBGPRINT(RT_DEBUG_TRACE, ("SYNC -pAd->StaActive.SupportedHtPhy.bHtEnable = TRUE\n"));
483 }
484 else
485 {
486 pAd->MlmeAux.HtCapabilityLen = 0;
487 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
488 }
489 // temporarily not support QOS in IBSS
490 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
491 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
492 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
493
494 AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, FALSE);
495 AsicLockChannel(pAd, pAd->MlmeAux.Channel);
496
497 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - MlmeStartReqAction(ch= %d,sup rates= %d, ext rates=%d)\n",
498 pAd->MlmeAux.Channel, pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
499
500 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
501 Status = MLME_SUCCESS;
502 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
503 }
504 else
505 {
506 DBGPRINT_ERR(("SYNC - MlmeStartReqAction() sanity check fail.\n"));
507 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
508 Status = MLME_INVALID_FORMAT;
509 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
510 }
511}
512
513/*
514 ==========================================================================
515 Description:
516 peer sends beacon back when scanning
517 ==========================================================================
518 */
519VOID PeerBeaconAtScanAction(
520 IN PRTMP_ADAPTER pAd,
521 IN MLME_QUEUE_ELEM *Elem)
522{
523 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
524 UCHAR Ssid[MAX_LEN_OF_SSID], BssType, Channel, NewChannel,
525 SsidLen, DtimCount, DtimPeriod, BcastFlag, MessageToMe;
526 CF_PARM CfParm;
527 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
528 PFRAME_802_11 pFrame;
529 LARGE_INTEGER TimeStamp;
530 UCHAR Erp;
531 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
532 UCHAR SupRateLen, ExtRateLen;
533 USHORT LenVIE;
534 UCHAR CkipFlag;
535 UCHAR AironetCellPowerLimit;
536 EDCA_PARM EdcaParm;
537 QBSS_LOAD_PARM QbssLoad;
538 QOS_CAPABILITY_PARM QosCapability;
539 ULONG RalinkIe;
540 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
541 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
542 HT_CAPABILITY_IE HtCapability;
543 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
544 UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
545 UCHAR AddHtInfoLen;
546 UCHAR NewExtChannelOffset = 0xff;
547
548
549 pFrame = (PFRAME_802_11) Elem->Msg;
550 // Init Variable IE structure
551 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
552 pVIE->Length = 0;
553
554 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
555 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
556
557 if (PeerBeaconAndProbeRspSanity(pAd,
558 Elem->Msg,
559 Elem->MsgLen,
560 Elem->Channel,
561 Addr2,
562 Bssid,
563 Ssid,
564 &SsidLen,
565 &BssType,
566 &BeaconPeriod,
567 &Channel,
568 &NewChannel,
569 &TimeStamp,
570 &CfParm,
571 &AtimWin,
572 &CapabilityInfo,
573 &Erp,
574 &DtimCount,
575 &DtimPeriod,
576 &BcastFlag,
577 &MessageToMe,
578 SupRate,
579 &SupRateLen,
580 ExtRate,
581 &ExtRateLen,
582 &CkipFlag,
583 &AironetCellPowerLimit,
584 &EdcaParm,
585 &QbssLoad,
586 &QosCapability,
587 &RalinkIe,
588 &HtCapabilityLen,
589 &PreNHtCapabilityLen,
590 &HtCapability,
591 &AddHtInfoLen,
592 &AddHtInfo,
593 &NewExtChannelOffset,
594 &LenVIE,
595 pVIE))
596 {
597 ULONG Idx;
598 CHAR Rssi = 0;
599
600 Idx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
601 if (Idx != BSS_NOT_FOUND)
602 Rssi = pAd->ScanTab.BssEntry[Idx].Rssi;
603
604 Rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
605
606 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
607 HtCapabilityLen = SIZE_HT_CAP_IE;
608
609 if ((pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED) && (Channel == pAd->StaCfg.CCXScanChannel))
610 {
611 Idx = BssTableSetEntry(pAd, &pAd->StaCfg.CCXBssTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
612 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen,ExtRate, ExtRateLen, &HtCapability,
613 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
614 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
615 if (Idx != BSS_NOT_FOUND)
616 {
617 NdisMoveMemory(pAd->StaCfg.CCXBssTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
618 NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
619 NdisMoveMemory(&pAd->StaCfg.CCXBssTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
620 if (pAd->StaCfg.CCXReqType == MSRN_TYPE_BEACON_REQ)
621 AironetAddBeaconReport(pAd, Idx, Elem);
622 }
623 }
624 else
625 {
626 Idx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
627 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
628 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, Rssi, TimeStamp, CkipFlag,
629 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
630
631 if (Idx != BSS_NOT_FOUND)
632 {
633 NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
634 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
635 NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
636 }
637 }
638 }
639 // sanity check fail, ignored
640}
641
642/*
643 ==========================================================================
644 Description:
645 When waiting joining the (I)BSS, beacon received from external
646 ==========================================================================
647 */
648VOID PeerBeaconAtJoinAction(
649 IN PRTMP_ADAPTER pAd,
650 IN MLME_QUEUE_ELEM *Elem)
651{
652 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
653 UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, BssType, Channel, MessageToMe,
654 DtimCount, DtimPeriod, BcastFlag, NewChannel;
655 LARGE_INTEGER TimeStamp;
656 USHORT BeaconPeriod, AtimWin, CapabilityInfo;
657 CF_PARM Cf;
658 BOOLEAN TimerCancelled;
659 UCHAR Erp;
660 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
661 UCHAR SupRateLen, ExtRateLen;
662 UCHAR CkipFlag;
663 USHORT LenVIE;
664 UCHAR AironetCellPowerLimit;
665 EDCA_PARM EdcaParm;
666 QBSS_LOAD_PARM QbssLoad;
667 QOS_CAPABILITY_PARM QosCapability;
668 USHORT Status;
669 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
670 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
671 ULONG RalinkIe;
672 ULONG Idx;
673 HT_CAPABILITY_IE HtCapability;
674 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
675 UCHAR HtCapabilityLen = 0, PreNHtCapabilityLen = 0;
676 UCHAR AddHtInfoLen;
677 UCHAR NewExtChannelOffset = 0xff;
678 UCHAR CentralChannel;
679
680 // Init Variable IE structure
681 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
682 pVIE->Length = 0;
683 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
684 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
685
686
687 if (PeerBeaconAndProbeRspSanity(pAd,
688 Elem->Msg,
689 Elem->MsgLen,
690 Elem->Channel,
691 Addr2,
692 Bssid,
693 Ssid,
694 &SsidLen,
695 &BssType,
696 &BeaconPeriod,
697 &Channel,
698 &NewChannel,
699 &TimeStamp,
700 &Cf,
701 &AtimWin,
702 &CapabilityInfo,
703 &Erp,
704 &DtimCount,
705 &DtimPeriod,
706 &BcastFlag,
707 &MessageToMe,
708 SupRate,
709 &SupRateLen,
710 ExtRate,
711 &ExtRateLen,
712 &CkipFlag,
713 &AironetCellPowerLimit,
714 &EdcaParm,
715 &QbssLoad,
716 &QosCapability,
717 &RalinkIe,
718 &HtCapabilityLen,
719 &PreNHtCapabilityLen,
720 &HtCapability,
721 &AddHtInfoLen,
722 &AddHtInfo,
723 &NewExtChannelOffset,
724 &LenVIE,
725 pVIE))
726 {
727 // Disqualify 11b only adhoc when we are in 11g only adhoc mode
728 if ((BssType == BSS_ADHOC) && (pAd->CommonCfg.PhyMode == PHY_11G) && ((SupRateLen+ExtRateLen)< 12))
729 return;
730
731 // BEACON from desired BSS/IBSS found. We should be able to decide most
732 // BSS parameters here.
733 // Q. But what happen if this JOIN doesn't conclude a successful ASSOCIATEION?
734 // Do we need to receover back all parameters belonging to previous BSS?
735 // A. Should be not. There's no back-door recover to previous AP. It still need
736 // a new JOIN-AUTH-ASSOC sequence.
737 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Bssid))
738 {
739 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired BEACON at JoinWaitBeacon... Channel = %d\n", Channel));
740 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &TimerCancelled);
741
742 // Update RSSI to prevent No signal display when cards first initialized
743 pAd->StaCfg.RssiSample.LastRssi0 = ConvertToRssi(pAd, Elem->Rssi0, RSSI_0);
744 pAd->StaCfg.RssiSample.LastRssi1 = ConvertToRssi(pAd, Elem->Rssi1, RSSI_1);
745 pAd->StaCfg.RssiSample.LastRssi2 = ConvertToRssi(pAd, Elem->Rssi2, RSSI_2);
746 pAd->StaCfg.RssiSample.AvgRssi0 = pAd->StaCfg.RssiSample.LastRssi0;
747 pAd->StaCfg.RssiSample.AvgRssi0X8 = pAd->StaCfg.RssiSample.AvgRssi0 << 3;
748 pAd->StaCfg.RssiSample.AvgRssi1 = pAd->StaCfg.RssiSample.LastRssi1;
749 pAd->StaCfg.RssiSample.AvgRssi1X8 = pAd->StaCfg.RssiSample.AvgRssi1 << 3;
750 pAd->StaCfg.RssiSample.AvgRssi2 = pAd->StaCfg.RssiSample.LastRssi2;
751 pAd->StaCfg.RssiSample.AvgRssi2X8 = pAd->StaCfg.RssiSample.AvgRssi2 << 3;
752
753 //
754 // We need to check if SSID only set to any, then we can record the current SSID.
755 // Otherwise will cause hidden SSID association failed.
756 //
757 if (pAd->MlmeAux.SsidLen == 0)
758 {
759 NdisMoveMemory(pAd->MlmeAux.Ssid, Ssid, SsidLen);
760 pAd->MlmeAux.SsidLen = SsidLen;
761 }
762 else
763 {
764 Idx = BssSsidTableSearch(&pAd->ScanTab, Bssid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Channel);
765
766 if (Idx != BSS_NOT_FOUND)
767 {
768 //
769 // Multiple SSID case, used correct CapabilityInfo
770 //
771 CapabilityInfo = pAd->ScanTab.BssEntry[Idx].CapabilityInfo;
772 }
773 }
774 NdisMoveMemory(pAd->MlmeAux.Bssid, Bssid, MAC_ADDR_LEN);
775 pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
776 pAd->MlmeAux.BssType = BssType;
777 pAd->MlmeAux.BeaconPeriod = BeaconPeriod;
778 pAd->MlmeAux.Channel = Channel;
779 pAd->MlmeAux.AtimWin = AtimWin;
780 pAd->MlmeAux.CfpPeriod = Cf.CfpPeriod;
781 pAd->MlmeAux.CfpMaxDuration = Cf.CfpMaxDuration;
782 pAd->MlmeAux.APRalinkIe = RalinkIe;
783
784 // Copy AP's supported rate to MlmeAux for creating assoication request
785 // Also filter out not supported rate
786 pAd->MlmeAux.SupRateLen = SupRateLen;
787 NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
788 RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
789 pAd->MlmeAux.ExtRateLen = ExtRateLen;
790 NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
791 RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
792
793 NdisZeroMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, 16);
794
795 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
796 pAd->MlmeAux.HtCapabilityLen = HtCapabilityLen;
797
798 // filter out un-supported ht rates
799 if (((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0)) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
800 {
801 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
802 RTMPMoveMemory(&pAd->MlmeAux.AddHtInfo, &AddHtInfo, SIZE_ADD_HT_INFO_IE);
803
804 // StaActive.SupportedHtPhy.MCSSet stores Peer AP's 11n Rx capability
805 NdisMoveMemory(pAd->StaActive.SupportedPhyInfo.MCSSet, HtCapability.MCSSet, 16);
806 pAd->MlmeAux.NewExtChannelOffset = NewExtChannelOffset;
807 pAd->MlmeAux.HtCapabilityLen = SIZE_HT_CAP_IE;
808 pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
809 if (PreNHtCapabilityLen > 0)
810 pAd->StaActive.SupportedPhyInfo.bPreNHt = TRUE;
811 RTMPCheckHt(pAd, BSSID_WCID, &HtCapability, &AddHtInfo);
812 // Copy AP Parameter to StaActive. This is also in LinkUp.
813 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction! (MpduDensity=%d, MaxRAmpduFactor=%d, BW=%d)\n",
814 pAd->StaActive.SupportedHtPhy.MpduDensity, pAd->StaActive.SupportedHtPhy.MaxRAmpduFactor, HtCapability.HtCapInfo.ChannelWidth));
815
816 if (AddHtInfoLen > 0)
817 {
818 CentralChannel = AddHtInfo.ControlChan;
819 // Check again the Bandwidth capability of this AP.
820 if ((AddHtInfo.ControlChan > 2)&& (AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
821 {
822 CentralChannel = AddHtInfo.ControlChan - 2;
823 }
824 else if ((AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (HtCapability.HtCapInfo.ChannelWidth == BW_40))
825 {
826 CentralChannel = AddHtInfo.ControlChan + 2;
827 }
828
829 // Check Error .
830 if (pAd->MlmeAux.CentralChannel != CentralChannel)
831 DBGPRINT(RT_DEBUG_ERROR, ("PeerBeaconAtJoinAction HT===>Beacon Central Channel = %d, Control Channel = %d. Mlmeaux CentralChannel = %d\n", CentralChannel, AddHtInfo.ControlChan, pAd->MlmeAux.CentralChannel));
832
833 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>Central Channel = %d, Control Channel = %d, .\n", CentralChannel, AddHtInfo.ControlChan));
834
835 }
836
837 }
838 else
839 {
840 // To prevent error, let legacy AP must have same CentralChannel and Channel.
841 if ((HtCapabilityLen == 0) && (PreNHtCapabilityLen == 0))
842 pAd->MlmeAux.CentralChannel = pAd->MlmeAux.Channel;
843
844 pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
845 RTMPZeroMemory(&pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
846 RTMPZeroMemory(&pAd->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE);
847 }
848
849 RTMPUpdateMlmeRate(pAd);
850
851 // copy QOS related information
852 if ((pAd->CommonCfg.bWmmCapable)
853 || (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
854 )
855 {
856 NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, &EdcaParm, sizeof(EDCA_PARM));
857 NdisMoveMemory(&pAd->MlmeAux.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
858 NdisMoveMemory(&pAd->MlmeAux.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
859 }
860 else
861 {
862 NdisZeroMemory(&pAd->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));
863 NdisZeroMemory(&pAd->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));
864 NdisZeroMemory(&pAd->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));
865 }
866
867 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n",
868 pAd->MlmeAux.SupRateLen, pAd->MlmeAux.ExtRateLen));
869
870 if (AironetCellPowerLimit != 0xFF)
871 {
872 //We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power
873 ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
874 }
875 else //Used the default TX Power Percentage.
876 pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
877
878 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
879 Status = MLME_SUCCESS;
880 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
881 }
882 // not to me BEACON, ignored
883 }
884 // sanity check fail, ignore this frame
885}
886
887/*
888 ==========================================================================
889 Description:
890 receive BEACON from peer
891
892 IRQL = DISPATCH_LEVEL
893
894 ==========================================================================
895 */
896VOID PeerBeacon(
897 IN PRTMP_ADAPTER pAd,
898 IN MLME_QUEUE_ELEM *Elem)
899{
900 UCHAR Bssid[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
901 CHAR Ssid[MAX_LEN_OF_SSID];
902 CF_PARM CfParm;
903 UCHAR SsidLen, MessageToMe=0, BssType, Channel, NewChannel, index=0;
904 UCHAR DtimCount=0, DtimPeriod=0, BcastFlag=0;
905 USHORT CapabilityInfo, AtimWin, BeaconPeriod;
906 LARGE_INTEGER TimeStamp;
907 USHORT TbttNumToNextWakeUp;
908 UCHAR Erp;
909 UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
910 UCHAR SupRateLen, ExtRateLen;
911 UCHAR CkipFlag;
912 USHORT LenVIE;
913 UCHAR AironetCellPowerLimit;
914 EDCA_PARM EdcaParm;
915 QBSS_LOAD_PARM QbssLoad;
916 QOS_CAPABILITY_PARM QosCapability;
917 ULONG RalinkIe;
918 // New for WPA security suites
919 UCHAR VarIE[MAX_VIE_LEN]; // Total VIE length = MAX_VIE_LEN - -5
920 NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
921 HT_CAPABILITY_IE HtCapability;
922 ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
923 UCHAR HtCapabilityLen, PreNHtCapabilityLen;
924 UCHAR AddHtInfoLen;
925 UCHAR NewExtChannelOffset = 0xff;
926
927 if (!(INFRA_ON(pAd) || ADHOC_ON(pAd)
928 ))
929 return;
930
931 // Init Variable IE structure
932 pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
933 pVIE->Length = 0;
934 RTMPZeroMemory(&HtCapability, sizeof(HtCapability));
935 RTMPZeroMemory(&AddHtInfo, sizeof(ADD_HT_INFO_IE));
936
937 if (PeerBeaconAndProbeRspSanity(pAd,
938 Elem->Msg,
939 Elem->MsgLen,
940 Elem->Channel,
941 Addr2,
942 Bssid,
943 Ssid,
944 &SsidLen,
945 &BssType,
946 &BeaconPeriod,
947 &Channel,
948 &NewChannel,
949 &TimeStamp,
950 &CfParm,
951 &AtimWin,
952 &CapabilityInfo,
953 &Erp,
954 &DtimCount,
955 &DtimPeriod,
956 &BcastFlag,
957 &MessageToMe,
958 SupRate,
959 &SupRateLen,
960 ExtRate,
961 &ExtRateLen,
962 &CkipFlag,
963 &AironetCellPowerLimit,
964 &EdcaParm,
965 &QbssLoad,
966 &QosCapability,
967 &RalinkIe,
968 &HtCapabilityLen,
969 &PreNHtCapabilityLen,
970 &HtCapability,
971 &AddHtInfoLen,
972 &AddHtInfo,
973 &NewExtChannelOffset,
974 &LenVIE,
975 pVIE))
976 {
977 BOOLEAN is_my_bssid, is_my_ssid;
978 ULONG Bssidx, Now;
979 BSS_ENTRY *pBss;
980 CHAR RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
981
982 is_my_bssid = MAC_ADDR_EQUAL(Bssid, pAd->CommonCfg.Bssid)? TRUE : FALSE;
983 is_my_ssid = SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)? TRUE:FALSE;
984
985
986 // ignore BEACON not for my SSID
987 if ((! is_my_ssid) && (! is_my_bssid))
988 return;
989
990 // It means STA waits disassoc completely from this AP, ignores this beacon.
991 if (pAd->Mlme.CntlMachine.CurrState == CNTL_WAIT_DISASSOC)
992 return;
993
994 // Copy Control channel for this BSSID.
995 if (AddHtInfoLen != 0)
996 Channel = AddHtInfo.ControlChan;
997
998 if ((HtCapabilityLen > 0) || (PreNHtCapabilityLen > 0))
999 HtCapabilityLen = SIZE_HT_CAP_IE;
1000
1001 //
1002 // Housekeeping "SsidBssTab" table for later-on ROAMing usage.
1003 //
1004 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1005 if (Bssidx == BSS_NOT_FOUND)
1006 {
1007 // discover new AP of this network, create BSS entry
1008 Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1009 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,
1010 &HtCapability, &AddHtInfo,HtCapabilityLen,AddHtInfoLen,NewExtChannelOffset, Channel,
1011 RealRssi, TimeStamp, CkipFlag, &EdcaParm, &QosCapability,
1012 &QbssLoad, LenVIE, pVIE);
1013 if (Bssidx == BSS_NOT_FOUND) // return if BSS table full
1014 return;
1015
1016 NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4);
1017 NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
1018 NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
1019
1020
1021
1022 }
1023
1024 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1025 {
1026 // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1027 // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1028 AsicSwitchChannel(pAd, 1, FALSE);
1029 AsicLockChannel(pAd, 1);
1030 LinkDown(pAd, FALSE);
1031 MlmeQueueInit(&pAd->Mlme.Queue);
1032 BssTableInit(&pAd->ScanTab);
1033 RTMPusecDelay(1000000); // use delay to prevent STA do reassoc
1034
1035 // channel sanity check
1036 for (index = 0 ; index < pAd->ChannelListNum; index++)
1037 {
1038 if (pAd->ChannelList[index].Channel == NewChannel)
1039 {
1040 pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
1041 pAd->CommonCfg.Channel = NewChannel;
1042 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1043 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1044 DBGPRINT(RT_DEBUG_TRACE, ("PeerBeacon - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
1045 break;
1046 }
1047 }
1048
1049 if (index >= pAd->ChannelListNum)
1050 {
1051 DBGPRINT_ERR(("PeerBeacon(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1052 }
1053 }
1054
1055 // if the ssid matched & bssid unmatched, we should select the bssid with large value.
1056 // This might happened when two STA start at the same time
1057 if ((! is_my_bssid) && ADHOC_ON(pAd))
1058 {
1059 INT i;
1060
1061 // Add the safeguard against the mismatch of adhoc wep status
1062 if (pAd->StaCfg.WepStatus != pAd->ScanTab.BssEntry[Bssidx].WepStatus)
1063 {
1064#ifdef RT30xx
1065 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - Not matched wep status %d %d\n", pAd->StaCfg.WepStatus, pAd->ScanTab.BssEntry[Bssidx].WepStatus));
1066 DBGPRINT(RT_DEBUG_TRACE, ("bssid=%s\n", pAd->ScanTab.BssEntry[Bssidx].Bssid));
1067#endif
1068 return;
1069 }
1070
1071 // collapse into the ADHOC network which has bigger BSSID value.
1072 for (i = 0; i < 6; i++)
1073 {
1074 if (Bssid[i] > pAd->CommonCfg.Bssid[i])
1075 {
1076 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - merge to the IBSS with bigger BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n",
1077 Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5]));
1078 AsicDisableSync(pAd);
1079 COPY_MAC_ADDR(pAd->CommonCfg.Bssid, Bssid);
1080 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1081 MakeIbssBeacon(pAd); // re-build BEACON frame
1082 AsicEnableIbssSync(pAd); // copy BEACON frame to on-chip memory
1083 is_my_bssid = TRUE;
1084 break;
1085 }
1086 else if (Bssid[i] < pAd->CommonCfg.Bssid[i])
1087 break;
1088 }
1089 }
1090
1091
1092 NdisGetSystemUpTime(&Now);
1093 pBss = &pAd->ScanTab.BssEntry[Bssidx];
1094 pBss->Rssi = RealRssi; // lastest RSSI
1095 pBss->LastBeaconRxTime = Now; // last RX timestamp
1096
1097 //
1098 // BEACON from my BSSID - either IBSS or INFRA network
1099 //
1100 if (is_my_bssid)
1101 {
1102 RXWI_STRUC RxWI;
1103
1104 pAd->StaCfg.DtimCount = DtimCount;
1105 pAd->StaCfg.DtimPeriod = DtimPeriod;
1106 pAd->StaCfg.LastBeaconRxTime = Now;
1107
1108
1109 RxWI.RSSI0 = Elem->Rssi0;
1110 RxWI.RSSI1 = Elem->Rssi1;
1111 RxWI.RSSI2 = Elem->Rssi2;
1112
1113 Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, &RxWI);
1114 if (AironetCellPowerLimit != 0xFF)
1115 {
1116 //
1117 // We get the Cisco (ccx) "TxPower Limit" required
1118 // Changed to appropriate TxPower Limit for Ciso Compatible Extensions
1119 //
1120 ChangeToCellPowerLimit(pAd, AironetCellPowerLimit);
1121 }
1122 else
1123 {
1124 //
1125 // AironetCellPowerLimit equal to 0xFF means the Cisco (ccx) "TxPower Limit" not exist.
1126 // Used the default TX Power Percentage, that set from UI.
1127 //
1128 pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
1129 }
1130
1131 if (ADHOC_ON(pAd) && (CAP_IS_IBSS_ON(CapabilityInfo)))
1132 {
1133 UCHAR MaxSupportedRateIn500Kbps = 0;
1134 UCHAR idx;
1135 MAC_TABLE_ENTRY *pEntry;
1136
1137 // supported rates array may not be sorted. sort it and find the maximum rate
1138 for (idx=0; idx<SupRateLen; idx++)
1139 {
1140 if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f))
1141 MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f;
1142 }
1143
1144 for (idx=0; idx<ExtRateLen; idx++)
1145 {
1146 if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f))
1147 MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f;
1148 }
1149
1150 // look up the existing table
1151 pEntry = MacTableLookup(pAd, Addr2);
1152
1153 // Ad-hoc mode is using MAC address as BA session. So we need to continuously find newly joined adhoc station by receiving beacon.
1154 // To prevent always check this, we use wcid == RESERVED_WCID to recognize it as newly joined adhoc station.
1155 if ((ADHOC_ON(pAd) && (Elem->Wcid == RESERVED_WCID)) ||
1156 (pEntry && ((pEntry->LastBeaconRxTime + ADHOC_ENTRY_BEACON_LOST_TIME) < Now)))
1157 {
1158 if (pEntry == NULL)
1159 // Another adhoc joining, add to our MAC table.
1160 pEntry = MacTableInsertEntry(pAd, Addr2, BSS0, FALSE);
1161
1162 if (StaAddMacTableEntry(pAd, pEntry, MaxSupportedRateIn500Kbps, &HtCapability, HtCapabilityLen, CapabilityInfo) == FALSE)
1163 {
1164 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC - Add Entry failed.\n"));
1165 return;
1166 }
1167
1168 if (pEntry &&
1169 (Elem->Wcid == RESERVED_WCID))
1170 {
1171 idx = pAd->StaCfg.DefaultKeyId;
1172 RT28XX_STA_SECURITY_INFO_ADD(pAd, BSS0, idx, pEntry);
1173 }
1174 }
1175
1176 if (pEntry && pEntry->ValidAsCLI)
1177 pEntry->LastBeaconRxTime = Now;
1178
1179 // At least another peer in this IBSS, declare MediaState as CONNECTED
1180 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1181 {
1182 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
1183
1184 pAd->IndicateMediaState = NdisMediaStateConnected;
1185 RTMP_IndicateMediaState(pAd);
1186 pAd->ExtraInfo = GENERAL_LINK_UP;
1187 AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
1188
1189 // 2003/03/12 - john
1190 // Make sure this entry in "ScanTab" table, thus complies to Microsoft's policy that
1191 // "site survey" result should always include the current connected network.
1192 //
1193 Bssidx = BssTableSearch(&pAd->ScanTab, Bssid, Channel);
1194 if (Bssidx == BSS_NOT_FOUND)
1195 {
1196 Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, Bssid, Ssid, SsidLen, BssType, BeaconPeriod,
1197 &CfParm, AtimWin, CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen, &HtCapability,
1198 &AddHtInfo, HtCapabilityLen, AddHtInfoLen, NewExtChannelOffset, Channel, RealRssi, TimeStamp, 0,
1199 &EdcaParm, &QosCapability, &QbssLoad, LenVIE, pVIE);
1200 }
1201 DBGPRINT(RT_DEBUG_TRACE, ("ADHOC fOP_STATUS_MEDIA_STATE_CONNECTED.\n"));
1202 }
1203 }
1204
1205 if (INFRA_ON(pAd))
1206 {
1207 BOOLEAN bUseShortSlot, bUseBGProtection;
1208
1209 // decide to use/change to -
1210 // 1. long slot (20 us) or short slot (9 us) time
1211 // 2. turn on/off RTS/CTS and/or CTS-to-self protection
1212 // 3. short preamble
1213
1214 //bUseShortSlot = pAd->CommonCfg.bUseShortSlotTime && CAP_IS_SHORT_SLOT(CapabilityInfo);
1215 bUseShortSlot = CAP_IS_SHORT_SLOT(CapabilityInfo);
1216 if (bUseShortSlot != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))
1217 AsicSetSlotTime(pAd, bUseShortSlot);
1218
1219 bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || // always use
1220 ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(Erp));
1221
1222 if (pAd->CommonCfg.Channel > 14) // always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP
1223 bUseBGProtection = FALSE;
1224
1225 if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
1226 {
1227 if (bUseBGProtection)
1228 {
1229 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1230 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),FALSE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1231 }
1232 else
1233 {
1234 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
1235 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, (OFDMSETPROTECT|CCKSETPROTECT|ALLN_SETPROTECT),TRUE,(pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1));
1236 }
1237
1238 DBGPRINT(RT_DEBUG_WARN, ("SYNC - AP changed B/G protection to %d\n", bUseBGProtection));
1239 }
1240
1241 // check Ht protection mode. and adhere to the Non-GF device indication by AP.
1242 if ((AddHtInfoLen != 0) &&
1243 ((AddHtInfo.AddHtInfo2.OperaionMode != pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode) ||
1244 (AddHtInfo.AddHtInfo2.NonGfPresent != pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent)))
1245 {
1246 pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent = AddHtInfo.AddHtInfo2.NonGfPresent;
1247 pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode = AddHtInfo.AddHtInfo2.OperaionMode;
1248 if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)
1249 {
1250 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE);
1251 }
1252 else
1253 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1254
1255 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP changed N OperaionMode to %d\n", pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode));
1256 }
1257
1258 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED) &&
1259 ERP_IS_USE_BARKER_PREAMBLE(Erp))
1260 {
1261 MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
1262 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP forced to use LONG preamble\n"));
1263 }
1264
1265 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) &&
1266 (EdcaParm.bValid == TRUE) &&
1267 (EdcaParm.EdcaUpdateCount != pAd->CommonCfg.APEdcaParm.EdcaUpdateCount))
1268 {
1269 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - AP change EDCA parameters(from %d to %d)\n",
1270 pAd->CommonCfg.APEdcaParm.EdcaUpdateCount,
1271 EdcaParm.EdcaUpdateCount));
1272 AsicSetEdcaParm(pAd, &EdcaParm);
1273 }
1274
1275 // copy QOS related information
1276 NdisMoveMemory(&pAd->CommonCfg.APQbssLoad, &QbssLoad, sizeof(QBSS_LOAD_PARM));
1277 NdisMoveMemory(&pAd->CommonCfg.APQosCapability, &QosCapability, sizeof(QOS_CAPABILITY_PARM));
1278 }
1279
1280 // only INFRASTRUCTURE mode support power-saving feature
1281 if ((INFRA_ON(pAd) && (pAd->StaCfg.Psm == PWR_SAVE)) || (pAd->CommonCfg.bAPSDForcePowerSave))
1282 {
1283 UCHAR FreeNumber;
1284 // 1. AP has backlogged unicast-to-me frame, stay AWAKE, send PSPOLL
1285 // 2. AP has backlogged broadcast/multicast frame and we want those frames, stay AWAKE
1286 // 3. we have outgoing frames in TxRing or MgmtRing, better stay AWAKE
1287 // 4. Psm change to PWR_SAVE, but AP not been informed yet, we better stay AWAKE
1288 // 5. otherwise, put PHY back to sleep to save battery.
1289 if (MessageToMe)
1290 {
1291 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable &&
1292 pAd->CommonCfg.bAPSDAC_BE && pAd->CommonCfg.bAPSDAC_BK && pAd->CommonCfg.bAPSDAC_VI && pAd->CommonCfg.bAPSDAC_VO)
1293 {
1294 pAd->CommonCfg.bNeedSendTriggerFrame = TRUE;
1295 }
1296 else
1297 RT28XX_PS_POLL_ENQUEUE(pAd);
1298 }
1299 else if (BcastFlag && (DtimCount == 0) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM))
1300 {
1301 }
1302 else if ((pAd->TxSwQueue[QID_AC_BK].Number != 0) ||
1303 (pAd->TxSwQueue[QID_AC_BE].Number != 0) ||
1304 (pAd->TxSwQueue[QID_AC_VI].Number != 0) ||
1305 (pAd->TxSwQueue[QID_AC_VO].Number != 0) ||
1306 (RTMPFreeTXDRequest(pAd, QID_AC_BK, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1307 (RTMPFreeTXDRequest(pAd, QID_AC_BE, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1308 (RTMPFreeTXDRequest(pAd, QID_AC_VI, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1309 (RTMPFreeTXDRequest(pAd, QID_AC_VO, TX_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS) ||
1310 (RTMPFreeTXDRequest(pAd, QID_MGMT, MGMT_RING_SIZE - 1, &FreeNumber) != NDIS_STATUS_SUCCESS))
1311 {
1312 // TODO: consider scheduled HCCA. might not be proper to use traditional DTIM-based power-saving scheme
1313 // can we cheat here (i.e. just check MGMT & AC_BE) for better performance?
1314 }
1315 else
1316 {
1317 USHORT NextDtim = DtimCount;
1318
1319 if (NextDtim == 0)
1320 NextDtim = DtimPeriod;
1321
1322 TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
1323 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
1324 TbttNumToNextWakeUp = NextDtim;
1325
1326 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1327 {
1328 AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
1329 }
1330 }
1331 }
1332 }
1333 // not my BSSID, ignore it
1334 }
1335 // sanity check fail, ignore this frame
1336}
1337
1338/*
1339 ==========================================================================
1340 Description:
1341 Receive PROBE REQ from remote peer when operating in IBSS mode
1342 ==========================================================================
1343 */
1344VOID PeerProbeReqAction(
1345 IN PRTMP_ADAPTER pAd,
1346 IN MLME_QUEUE_ELEM *Elem)
1347{
1348 UCHAR Addr2[MAC_ADDR_LEN];
1349 CHAR Ssid[MAX_LEN_OF_SSID];
1350 UCHAR SsidLen;
1351 UCHAR HtLen, AddHtLen, NewExtLen;
1352 HEADER_802_11 ProbeRspHdr;
1353 NDIS_STATUS NStatus;
1354 PUCHAR pOutBuffer = NULL;
1355 ULONG FrameLen = 0;
1356 LARGE_INTEGER FakeTimestamp;
1357 UCHAR DsLen = 1, IbssLen = 2;
1358 UCHAR LocalErpIe[3] = {IE_ERP, 1, 0};
1359 BOOLEAN Privacy;
1360 USHORT CapabilityInfo;
1361 UCHAR RSNIe = IE_WPA;
1362
1363 if (! ADHOC_ON(pAd))
1364 return;
1365
1366 if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen))
1367 {
1368 if ((SsidLen == 0) || SSID_EQUAL(Ssid, SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1369 {
1370 // allocate and send out ProbeRsp frame
1371 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1372 if (NStatus != NDIS_STATUS_SUCCESS)
1373 return;
1374
1375 //pAd->StaCfg.AtimWin = 0; // ??????
1376
1377 Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
1378 (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
1379 (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
1380 CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0);
1381
1382 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1383 sizeof(HEADER_802_11), &ProbeRspHdr,
1384 TIMESTAMP_LEN, &FakeTimestamp,
1385 2, &pAd->CommonCfg.BeaconPeriod,
1386 2, &CapabilityInfo,
1387 1, &SsidIe,
1388 1, &pAd->CommonCfg.SsidLen,
1389 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1390 1, &SupRateIe,
1391 1, &pAd->StaActive.SupRateLen,
1392 pAd->StaActive.SupRateLen, pAd->StaActive.SupRate,
1393 1, &DsIe,
1394 1, &DsLen,
1395 1, &pAd->CommonCfg.Channel,
1396 1, &IbssIe,
1397 1, &IbssLen,
1398 2, &pAd->StaActive.AtimWin,
1399 END_OF_ARGS);
1400
1401 if (pAd->StaActive.ExtRateLen)
1402 {
1403 ULONG tmp;
1404 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1405 3, LocalErpIe,
1406 1, &ExtRateIe,
1407 1, &pAd->StaActive.ExtRateLen,
1408 pAd->StaActive.ExtRateLen, &pAd->StaActive.ExtRate,
1409 END_OF_ARGS);
1410 FrameLen += tmp;
1411 }
1412
1413 // If adhoc secruity is set for WPA-None, append the cipher suite IE
1414 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
1415 {
1416 ULONG tmp;
1417 MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1418 1, &RSNIe,
1419 1, &pAd->StaCfg.RSNIE_Len,
1420 pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
1421 END_OF_ARGS);
1422 FrameLen += tmp;
1423 }
1424
1425 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1426 {
1427 ULONG TmpLen;
1428 UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
1429 HtLen = sizeof(pAd->CommonCfg.HtCapability);
1430 AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo);
1431 NewExtLen = 1;
1432 //New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame
1433 if (pAd->bBroadComHT == TRUE)
1434 {
1435 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1436 1, &WpaIe,
1437 4, &BROADCOM[0],
1438 pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
1439 END_OF_ARGS);
1440 }
1441 else
1442 {
1443 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1444 1, &HtCapIe,
1445 1, &HtLen,
1446 sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability,
1447 1, &AddHtInfoIe,
1448 1, &AddHtLen,
1449 sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo,
1450 1, &NewExtChanIe,
1451 1, &NewExtLen,
1452 sizeof(NEW_EXT_CHAN_IE), &pAd->CommonCfg.NewExtChanOffset,
1453 END_OF_ARGS);
1454 }
1455 FrameLen += TmpLen;
1456 }
1457
1458 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1459 MlmeFreeMemory(pAd, pOutBuffer);
1460 }
1461 }
1462}
1463
1464VOID BeaconTimeoutAtJoinAction(
1465 IN PRTMP_ADAPTER pAd,
1466 IN MLME_QUEUE_ELEM *Elem)
1467{
1468 USHORT Status;
1469 DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BeaconTimeoutAtJoinAction\n"));
1470 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1471 Status = MLME_REJ_TIMEOUT;
1472 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1473}
1474
1475/*
1476 ==========================================================================
1477 Description:
1478 Scan timeout procedure. basically add channel index by 1 and rescan
1479 ==========================================================================
1480 */
1481VOID ScanTimeoutAction(
1482 IN PRTMP_ADAPTER pAd,
1483 IN MLME_QUEUE_ELEM *Elem)
1484{
1485 pAd->MlmeAux.Channel = NextChannel(pAd, pAd->MlmeAux.Channel);
1486
1487 // Only one channel scanned for CISCO beacon request
1488 if ((pAd->MlmeAux.ScanType == SCAN_CISCO_ACTIVE) ||
1489 (pAd->MlmeAux.ScanType == SCAN_CISCO_PASSIVE) ||
1490 (pAd->MlmeAux.ScanType == SCAN_CISCO_NOISE) ||
1491 (pAd->MlmeAux.ScanType == SCAN_CISCO_CHANNEL_LOAD))
1492 pAd->MlmeAux.Channel = 0;
1493
1494 // this routine will stop if pAd->MlmeAux.Channel == 0
1495 ScanNextChannel(pAd);
1496}
1497
1498/*
1499 ==========================================================================
1500 Description:
1501 ==========================================================================
1502 */
1503VOID InvalidStateWhenScan(
1504 IN PRTMP_ADAPTER pAd,
1505 IN MLME_QUEUE_ELEM *Elem)
1506{
1507 USHORT Status;
1508 DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1509 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1510 Status = MLME_STATE_MACHINE_REJECT;
1511 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
1512}
1513
1514/*
1515 ==========================================================================
1516 Description:
1517 ==========================================================================
1518 */
1519VOID InvalidStateWhenJoin(
1520 IN PRTMP_ADAPTER pAd,
1521 IN MLME_QUEUE_ELEM *Elem)
1522{
1523 USHORT Status;
1524 DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenJoin(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1525 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1526 Status = MLME_STATE_MACHINE_REJECT;
1527 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_JOIN_CONF, 2, &Status);
1528}
1529
1530/*
1531 ==========================================================================
1532 Description:
1533 ==========================================================================
1534 */
1535VOID InvalidStateWhenStart(
1536 IN PRTMP_ADAPTER pAd,
1537 IN MLME_QUEUE_ELEM *Elem)
1538{
1539 USHORT Status;
1540 DBGPRINT(RT_DEBUG_TRACE, ("InvalidStateWhenStart(state=%ld). Reset SYNC machine\n", pAd->Mlme.SyncMachine.CurrState));
1541 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
1542 Status = MLME_STATE_MACHINE_REJECT;
1543 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_START_CONF, 2, &Status);
1544}
1545
1546/*
1547 ==========================================================================
1548 Description:
1549
1550 IRQL = DISPATCH_LEVEL
1551
1552 ==========================================================================
1553 */
1554VOID EnqueuePsPoll(
1555 IN PRTMP_ADAPTER pAd)
1556{
1557 if (pAd->StaCfg.WindowsPowerMode == Ndis802_11PowerModeLegacy_PSP)
1558 pAd->PsPollFrame.FC.PwrMgmt = PWR_SAVE;
1559 MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
1560}
1561
1562
1563/*
1564 ==========================================================================
1565 Description:
1566 ==========================================================================
1567 */
1568VOID EnqueueProbeRequest(
1569 IN PRTMP_ADAPTER pAd)
1570{
1571 NDIS_STATUS NState;
1572 PUCHAR pOutBuffer;
1573 ULONG FrameLen = 0;
1574 HEADER_802_11 Hdr80211;
1575
1576 DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n"));
1577
1578 NState = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1579 if (NState == NDIS_STATUS_SUCCESS)
1580 {
1581 MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
1582
1583 // this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse
1584 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1585 sizeof(HEADER_802_11), &Hdr80211,
1586 1, &SsidIe,
1587 1, &pAd->CommonCfg.SsidLen,
1588 pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
1589 1, &SupRateIe,
1590 1, &pAd->StaActive.SupRateLen,
1591 pAd->StaActive.SupRateLen, pAd->StaActive.SupRate,
1592 END_OF_ARGS);
1593 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
1594 MlmeFreeMemory(pAd, pOutBuffer);
1595 }
1596
1597}
1598
1599BOOLEAN ScanRunning(
1600 IN PRTMP_ADAPTER pAd)
1601{
1602 return (pAd->Mlme.SyncMachine.CurrState == SCAN_LISTEN) ? TRUE : FALSE;
1603}
1604
diff --git a/drivers/staging/rt2870/sta/wpa.c b/drivers/staging/rt2870/sta/wpa.c
index 58274364d78c..57a2eb2d0896 100644
--- a/drivers/staging/rt2870/sta/wpa.c
+++ b/drivers/staging/rt2870/sta/wpa.c
@@ -1,2100 +1 @@
1/* #include "../../rt2860/sta/wpa.c"
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 wpa.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 Jan Lee 03-07-22 Initial
36 Paul Lin 03-11-28 Modify for supplicant
37*/
38#include "../rt_config.h"
39
40#define WPARSNIE 0xdd
41#define WPA2RSNIE 0x30
42
43//extern UCHAR BIT8[];
44UCHAR CipherWpaPskTkip[] = {
45 0xDD, 0x16, // RSN IE
46 0x00, 0x50, 0xf2, 0x01, // oui
47 0x01, 0x00, // Version
48 0x00, 0x50, 0xf2, 0x02, // Multicast
49 0x01, 0x00, // Number of unicast
50 0x00, 0x50, 0xf2, 0x02, // unicast
51 0x01, 0x00, // number of authentication method
52 0x00, 0x50, 0xf2, 0x02 // authentication
53 };
54UCHAR CipherWpaPskTkipLen = (sizeof(CipherWpaPskTkip) / sizeof(UCHAR));
55
56UCHAR CipherWpaPskAes[] = {
57 0xDD, 0x16, // RSN IE
58 0x00, 0x50, 0xf2, 0x01, // oui
59 0x01, 0x00, // Version
60 0x00, 0x50, 0xf2, 0x04, // Multicast
61 0x01, 0x00, // Number of unicast
62 0x00, 0x50, 0xf2, 0x04, // unicast
63 0x01, 0x00, // number of authentication method
64 0x00, 0x50, 0xf2, 0x02 // authentication
65 };
66UCHAR CipherWpaPskAesLen = (sizeof(CipherWpaPskAes) / sizeof(UCHAR));
67
68UCHAR CipherSuiteCiscoCCKM[] = {
69 0xDD, 0x16, // RSN IE
70 0x00, 0x50, 0xf2, 0x01, // oui
71 0x01, 0x00, // Version
72 0x00, 0x40, 0x96, 0x01, // Multicast
73 0x01, 0x00, // Number of uicast
74 0x00, 0x40, 0x96, 0x01, // unicast
75 0x01, 0x00, // number of authentication method
76 0x00, 0x40, 0x96, 0x00 // Authentication
77 };
78UCHAR CipherSuiteCiscoCCKMLen = (sizeof(CipherSuiteCiscoCCKM) / sizeof(UCHAR));
79
80UCHAR CipherSuiteCiscoCCKM24[] = {
81 0xDD, 0x18, // RSN IE
82 0x00, 0x50, 0xf2, 0x01, // oui
83 0x01, 0x00, // Version
84 0x00, 0x40, 0x96, 0x01, // Multicast
85 0x01, 0x00, // Number of uicast
86 0x00, 0x40, 0x96, 0x01, // unicast
87 0x01, 0x00, // number of authentication method
88 0x00, 0x40, 0x96, 0x00,
89 0x28, 0x00// Authentication
90 };
91
92UCHAR CipherSuiteCiscoCCKM24Len = (sizeof(CipherSuiteCiscoCCKM24) / sizeof(UCHAR));
93
94UCHAR CipherSuiteCCXTkip[] = {
95 0xDD, 0x16, // RSN IE
96 0x00, 0x50, 0xf2, 0x01, // oui
97 0x01, 0x00, // Version
98 0x00, 0x50, 0xf2, 0x02, // Multicast
99 0x01, 0x00, // Number of unicast
100 0x00, 0x50, 0xf2, 0x02, // unicast
101 0x01, 0x00, // number of authentication method
102 0x00, 0x50, 0xf2, 0x01 // authentication
103 };
104UCHAR CipherSuiteCCXTkipLen = (sizeof(CipherSuiteCCXTkip) / sizeof(UCHAR));
105
106UCHAR CCX_LLC_HDR[] = {0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
107UCHAR LLC_NORMAL[] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
108
109UCHAR EAPOL_FRAME[] = {0x88, 0x8E};
110
111BOOLEAN CheckRSNIE(
112 IN PRTMP_ADAPTER pAd,
113 IN PUCHAR pData,
114 IN UCHAR DataLen,
115 OUT UCHAR *Offset);
116
117void inc_byte_array(UCHAR *counter, int len);
118
119/*
120 ========================================================================
121
122 Routine Description:
123 Classify WPA EAP message type
124
125 Arguments:
126 EAPType Value of EAP message type
127 MsgType Internal Message definition for MLME state machine
128
129 Return Value:
130 TRUE Found appropriate message type
131 FALSE No appropriate message type
132
133 IRQL = DISPATCH_LEVEL
134
135 Note:
136 All these constants are defined in wpa.h
137 For supplicant, there is only EAPOL Key message avaliable
138
139 ========================================================================
140*/
141BOOLEAN WpaMsgTypeSubst(
142 IN UCHAR EAPType,
143 OUT INT *MsgType)
144{
145 switch (EAPType)
146 {
147 case EAPPacket:
148 *MsgType = MT2_EAPPacket;
149 break;
150 case EAPOLStart:
151 *MsgType = MT2_EAPOLStart;
152 break;
153 case EAPOLLogoff:
154 *MsgType = MT2_EAPOLLogoff;
155 break;
156 case EAPOLKey:
157 *MsgType = MT2_EAPOLKey;
158 break;
159 case EAPOLASFAlert:
160 *MsgType = MT2_EAPOLASFAlert;
161 break;
162 default:
163 return FALSE;
164 }
165 return TRUE;
166}
167
168/*
169 ==========================================================================
170 Description:
171 association state machine init, including state transition and timer init
172 Parameters:
173 S - pointer to the association state machine
174 ==========================================================================
175 */
176VOID WpaPskStateMachineInit(
177 IN PRTMP_ADAPTER pAd,
178 IN STATE_MACHINE *S,
179 OUT STATE_MACHINE_FUNC Trans[])
180{
181 StateMachineInit(S, Trans, MAX_WPA_PSK_STATE, MAX_WPA_PSK_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PSK_IDLE, WPA_MACHINE_BASE);
182 StateMachineSetAction(S, WPA_PSK_IDLE, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction);
183}
184
185/*
186 ==========================================================================
187 Description:
188 This is state machine function.
189 When receiving EAPOL packets which is for 802.1x key management.
190 Use both in WPA, and WPAPSK case.
191 In this function, further dispatch to different functions according to the received packet. 3 categories are :
192 1. normal 4-way pairwisekey and 2-way groupkey handshake
193 2. MIC error (Countermeasures attack) report packet from STA.
194 3. Request for pairwise/group key update from STA
195 Return:
196 ==========================================================================
197*/
198VOID WpaEAPOLKeyAction(
199 IN PRTMP_ADAPTER pAd,
200 IN MLME_QUEUE_ELEM *Elem)
201
202{
203 INT MsgType = EAPOL_MSG_INVALID;
204 PKEY_DESCRIPTER pKeyDesc;
205 PHEADER_802_11 pHeader; //red
206 UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY];
207 UCHAR EapolVr;
208 KEY_INFO peerKeyInfo;
209
210 DBGPRINT(RT_DEBUG_TRACE, ("-----> WpaEAPOLKeyAction\n"));
211
212 // Get 802.11 header first
213 pHeader = (PHEADER_802_11) Elem->Msg;
214
215 // Get EAPoL-Key Descriptor
216 pKeyDesc = (PKEY_DESCRIPTER) &Elem->Msg[(LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H)];
217
218 NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
219 NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pKeyDesc->KeyInfo, sizeof(KEY_INFO));
220
221 *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo));
222
223
224 // 1. Check EAPOL frame version and type
225 EapolVr = (UCHAR) Elem->Msg[LENGTH_802_11+LENGTH_802_1_H];
226
227 if (((EapolVr != EAPOL_VER) && (EapolVr != EAPOL_VER2)) || ((pKeyDesc->Type != WPA1_KEY_DESC) && (pKeyDesc->Type != WPA2_KEY_DESC)))
228 {
229 DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n"));
230 return;
231 }
232
233 // First validate replay counter, only accept message with larger replay counter
234 // Let equal pass, some AP start with all zero replay counter
235 NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
236
237 if((RTMPCompareMemory(pKeyDesc->ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
238 (RTMPCompareMemory(pKeyDesc->ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
239 {
240 DBGPRINT(RT_DEBUG_ERROR, (" ReplayCounter not match \n"));
241 return;
242 }
243
244 // Process WPA2PSK frame
245 if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
246 {
247 if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
248 (peerKeyInfo.EKD_DL == 0) &&
249 (peerKeyInfo.KeyAck == 1) &&
250 (peerKeyInfo.KeyMic == 0) &&
251 (peerKeyInfo.Secure == 0) &&
252 (peerKeyInfo.Error == 0) &&
253 (peerKeyInfo.Request == 0))
254 {
255 MsgType = EAPOL_PAIR_MSG_1;
256 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n"));
257 } else if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
258 (peerKeyInfo.EKD_DL == 1) &&
259 (peerKeyInfo.KeyAck == 1) &&
260 (peerKeyInfo.KeyMic == 1) &&
261 (peerKeyInfo.Secure == 1) &&
262 (peerKeyInfo.Error == 0) &&
263 (peerKeyInfo.Request == 0))
264 {
265 MsgType = EAPOL_PAIR_MSG_3;
266 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n"));
267 } else if((peerKeyInfo.KeyType == GROUPKEY) &&
268 (peerKeyInfo.EKD_DL == 1) &&
269 (peerKeyInfo.KeyAck == 1) &&
270 (peerKeyInfo.KeyMic == 1) &&
271 (peerKeyInfo.Secure == 1) &&
272 (peerKeyInfo.Error == 0) &&
273 (peerKeyInfo.Request == 0))
274 {
275 MsgType = EAPOL_GROUP_MSG_1;
276 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n"));
277 }
278
279 // We will assume link is up (assoc suceess and port not secured).
280 // All state has to be able to process message from previous state
281 switch(pAd->StaCfg.WpaState)
282 {
283 case SS_START:
284 if(MsgType == EAPOL_PAIR_MSG_1)
285 {
286 Wpa2PairMsg1Action(pAd, Elem);
287 pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
288 }
289 break;
290
291 case SS_WAIT_MSG_3:
292 if(MsgType == EAPOL_PAIR_MSG_1)
293 {
294 Wpa2PairMsg1Action(pAd, Elem);
295 pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
296 }
297 else if(MsgType == EAPOL_PAIR_MSG_3)
298 {
299 Wpa2PairMsg3Action(pAd, Elem);
300 pAd->StaCfg.WpaState = SS_WAIT_GROUP;
301 }
302 break;
303
304 case SS_WAIT_GROUP: // When doing group key exchange
305 case SS_FINISH: // This happened when update group key
306 if(MsgType == EAPOL_PAIR_MSG_1)
307 {
308 // Reset port secured variable
309 pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
310 Wpa2PairMsg1Action(pAd, Elem);
311 pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
312 }
313 else if(MsgType == EAPOL_PAIR_MSG_3)
314 {
315 // Reset port secured variable
316 pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
317 Wpa2PairMsg3Action(pAd, Elem);
318 pAd->StaCfg.WpaState = SS_WAIT_GROUP;
319 }
320 else if(MsgType == EAPOL_GROUP_MSG_1)
321 {
322 WpaGroupMsg1Action(pAd, Elem);
323 pAd->StaCfg.WpaState = SS_FINISH;
324 }
325 break;
326
327 default:
328 break;
329 }
330 }
331 // Process WPAPSK Frame
332 // Classify message Type, either pairwise message 1, 3, or group message 1 for supplicant
333 else if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
334 {
335 if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
336 (peerKeyInfo.KeyIndex == 0) &&
337 (peerKeyInfo.KeyAck == 1) &&
338 (peerKeyInfo.KeyMic == 0) &&
339 (peerKeyInfo.Secure == 0) &&
340 (peerKeyInfo.Error == 0) &&
341 (peerKeyInfo.Request == 0))
342 {
343 MsgType = EAPOL_PAIR_MSG_1;
344 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 1\n"));
345 }
346 else if((peerKeyInfo.KeyType == PAIRWISEKEY) &&
347 (peerKeyInfo.KeyIndex == 0) &&
348 (peerKeyInfo.KeyAck == 1) &&
349 (peerKeyInfo.KeyMic == 1) &&
350 (peerKeyInfo.Secure == 0) &&
351 (peerKeyInfo.Error == 0) &&
352 (peerKeyInfo.Request == 0))
353 {
354 MsgType = EAPOL_PAIR_MSG_3;
355 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Pairwise Message 3\n"));
356 }
357 else if((peerKeyInfo.KeyType == GROUPKEY) &&
358 (peerKeyInfo.KeyIndex != 0) &&
359 (peerKeyInfo.KeyAck == 1) &&
360 (peerKeyInfo.KeyMic == 1) &&
361 (peerKeyInfo.Secure == 1) &&
362 (peerKeyInfo.Error == 0) &&
363 (peerKeyInfo.Request == 0))
364 {
365 MsgType = EAPOL_GROUP_MSG_1;
366 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL Key Group Message 1\n"));
367 }
368
369 // We will assume link is up (assoc suceess and port not secured).
370 // All state has to be able to process message from previous state
371 switch(pAd->StaCfg.WpaState)
372 {
373 case SS_START:
374 if(MsgType == EAPOL_PAIR_MSG_1)
375 {
376 WpaPairMsg1Action(pAd, Elem);
377 pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
378 }
379 break;
380
381 case SS_WAIT_MSG_3:
382 if(MsgType == EAPOL_PAIR_MSG_1)
383 {
384 WpaPairMsg1Action(pAd, Elem);
385 pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
386 }
387 else if(MsgType == EAPOL_PAIR_MSG_3)
388 {
389 WpaPairMsg3Action(pAd, Elem);
390 pAd->StaCfg.WpaState = SS_WAIT_GROUP;
391 }
392 break;
393
394 case SS_WAIT_GROUP: // When doing group key exchange
395 case SS_FINISH: // This happened when update group key
396 if(MsgType == EAPOL_PAIR_MSG_1)
397 {
398 WpaPairMsg1Action(pAd, Elem);
399 pAd->StaCfg.WpaState = SS_WAIT_MSG_3;
400 // Reset port secured variable
401 pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
402 }
403 else if(MsgType == EAPOL_PAIR_MSG_3)
404 {
405 WpaPairMsg3Action(pAd, Elem);
406 pAd->StaCfg.WpaState = SS_WAIT_GROUP;
407 // Reset port secured variable
408 pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
409 }
410 else if(MsgType == EAPOL_GROUP_MSG_1)
411 {
412 WpaGroupMsg1Action(pAd, Elem);
413 pAd->StaCfg.WpaState = SS_FINISH;
414 }
415 break;
416
417 default:
418 break;
419 }
420 }
421
422 DBGPRINT(RT_DEBUG_TRACE, ("<----- WpaEAPOLKeyAction\n"));
423}
424
425/*
426 ========================================================================
427
428 Routine Description:
429 Process Pairwise key 4-way handshaking
430
431 Arguments:
432 pAd Pointer to our adapter
433 Elem Message body
434
435 Return Value:
436 None
437
438 Note:
439
440 ========================================================================
441*/
442VOID WpaPairMsg1Action(
443 IN PRTMP_ADAPTER pAd,
444 IN MLME_QUEUE_ELEM *Elem)
445{
446 PHEADER_802_11 pHeader;
447 UCHAR *mpool, *PTK, *digest;
448 PUCHAR pOutBuffer = NULL;
449 UCHAR Header802_3[14];
450 ULONG FrameLen = 0;
451 PEAPOL_PACKET pMsg1;
452 EAPOL_PACKET Packet;
453 UCHAR Mic[16];
454
455 DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action ----->\n"));
456
457 // allocate memory pool
458 os_alloc_mem(pAd, (PUCHAR *)&mpool, 256);
459
460 if (mpool == NULL)
461 return;
462
463 // PTK Len = 80.
464 PTK = (UCHAR *) ROUND_UP(mpool, 4);
465 // digest Len = 80.
466 digest = (UCHAR *) ROUND_UP(PTK + 80, 4);
467
468 pHeader = (PHEADER_802_11) Elem->Msg;
469
470 // Process message 1 from authenticator
471 pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
472
473 // 1. Save Replay counter, it will use to verify message 3 and construct message 2
474 NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
475
476 // 2. Save ANonce
477 NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
478
479 // Generate random SNonce
480 GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce);
481
482 // Calc PTK(ANonce, SNonce)
483 WpaCountPTK(pAd,
484 pAd->StaCfg.PMK,
485 pAd->StaCfg.ANonce,
486 pAd->CommonCfg.Bssid,
487 pAd->StaCfg.SNonce,
488 pAd->CurrentAddress,
489 PTK,
490 LEN_PTK);
491
492 // Save key to PTK entry
493 NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK);
494
495 // init 802.3 header and Fill Packet
496 MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
497
498 // Zero Message 2 body
499 NdisZeroMemory(&Packet, sizeof(Packet));
500 Packet.ProVer = EAPOL_VER;
501 Packet.ProType = EAPOLKey;
502 //
503 // Message 2 as EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
504 //
505 Packet.KeyDesc.Type = WPA1_KEY_DESC;
506 // 1. Key descriptor version and appropriate RSN IE
507 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
508 {
509 Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
510 }
511 else // TKIP
512 {
513 Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
514 }
515
516 // fill in Data Material and its length
517 Packet.KeyDesc.KeyData[0] = IE_WPA;
518 Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len;
519 Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2;
520 NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
521
522 // Update packet length after decide Key data payload
523 Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1];
524
525 // Update Key length
526 Packet.KeyDesc.KeyLength[0] = pMsg1->KeyDesc.KeyLength[0];
527 Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1];
528 // 2. Key Type PeerKey
529 Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
530
531 // 3. KeyMic field presented
532 Packet.KeyDesc.KeyInfo.KeyMic = 1;
533
534 //Convert to little-endian format.
535 *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
536
537
538 // 4. Fill SNonce
539 NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE);
540
541 // 5. Key Replay Count
542 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
543
544 // Send EAPOL(0, 1, 0, 0, 0, P, 0, SNonce, MIC, RSN_IE)
545 // Out buffer for transmitting message 2
546 MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory
547 if(pOutBuffer == NULL)
548 {
549 os_free_mem(pAd, mpool);
550 return;
551 }
552 // Prepare EAPOL frame for MIC calculation
553 // Be careful, only EAPOL frame is counted for MIC calculation
554 MakeOutgoingFrame(pOutBuffer, &FrameLen,
555 Packet.Body_Len[1] + 4, &Packet,
556 END_OF_ARGS);
557
558 // 6. Prepare and Fill MIC value
559 NdisZeroMemory(Mic, sizeof(Mic));
560 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
561 { // AES
562
563 HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
564 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
565 }
566 else
567 { // TKIP
568 hmac_md5(PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
569 }
570 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
571
572 //hex_dump("MIC", Mic, LEN_KEY_DESC_MIC);
573
574 MakeOutgoingFrame(pOutBuffer, &FrameLen,
575 LENGTH_802_3, &Header802_3,
576 Packet.Body_Len[1] + 4, &Packet,
577 END_OF_ARGS);
578
579
580 // 5. Copy frame to Tx ring and send Msg 2 to authenticator
581 RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
582
583 MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
584 os_free_mem(pAd, (PUCHAR)mpool);
585
586 DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg1Action <-----\n"));
587}
588
589VOID Wpa2PairMsg1Action(
590 IN PRTMP_ADAPTER pAd,
591 IN MLME_QUEUE_ELEM *Elem)
592{
593 PHEADER_802_11 pHeader;
594 UCHAR *mpool, *PTK, *digest;
595 PUCHAR pOutBuffer = NULL;
596 UCHAR Header802_3[14];
597 ULONG FrameLen = 0;
598 PEAPOL_PACKET pMsg1;
599 EAPOL_PACKET Packet;
600 UCHAR Mic[16];
601
602 DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action ----->\n"));
603
604 // allocate memory pool
605 os_alloc_mem(pAd, (PUCHAR *)&mpool, 256);
606
607 if (mpool == NULL)
608 return;
609
610 // PTK Len = 80.
611 PTK = (UCHAR *) ROUND_UP(mpool, 4);
612 // digest Len = 80.
613 digest = (UCHAR *) ROUND_UP(PTK + 80, 4);
614
615 pHeader = (PHEADER_802_11) Elem->Msg;
616
617 // Process message 1 from authenticator
618 pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
619
620 // 1. Save Replay counter, it will use to verify message 3 and construct message 2
621 NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
622
623 // 2. Save ANonce
624 NdisMoveMemory(pAd->StaCfg.ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
625
626 // Generate random SNonce
627 GenRandom(pAd, pAd->CurrentAddress, pAd->StaCfg.SNonce);
628
629 if(pMsg1->KeyDesc.KeyDataLen[1] > 0 )
630 {
631 // cached PMKID
632 }
633
634 // Calc PTK(ANonce, SNonce)
635 WpaCountPTK(pAd,
636 pAd->StaCfg.PMK,
637 pAd->StaCfg.ANonce,
638 pAd->CommonCfg.Bssid,
639 pAd->StaCfg.SNonce,
640 pAd->CurrentAddress,
641 PTK,
642 LEN_PTK);
643
644 // Save key to PTK entry
645 NdisMoveMemory(pAd->StaCfg.PTK, PTK, LEN_PTK);
646
647 // init 802.3 header and Fill Packet
648 MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
649
650 // Zero message 2 body
651 NdisZeroMemory(&Packet, sizeof(Packet));
652 Packet.ProVer = EAPOL_VER;
653 Packet.ProType = EAPOLKey;
654 //
655 // Message 2 as EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
656 //
657 Packet.KeyDesc.Type = WPA2_KEY_DESC;
658
659 // 1. Key descriptor version and appropriate RSN IE
660 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
661 {
662 Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
663 }
664 else // TKIP
665 {
666 Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
667 }
668
669 // fill in Data Material and its length
670 Packet.KeyDesc.KeyData[0] = IE_WPA2;
671 Packet.KeyDesc.KeyData[1] = pAd->StaCfg.RSNIE_Len;
672 Packet.KeyDesc.KeyDataLen[1] = pAd->StaCfg.RSNIE_Len + 2;
673 NdisMoveMemory(&Packet.KeyDesc.KeyData[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
674
675 // Update packet length after decide Key data payload
676 Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + Packet.KeyDesc.KeyDataLen[1];
677
678 // 2. Key Type PeerKey
679 Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
680
681 // 3. KeyMic field presented
682 Packet.KeyDesc.KeyInfo.KeyMic = 1;
683
684 // Update Key Length
685 Packet.KeyDesc.KeyLength[0] = 0;
686 Packet.KeyDesc.KeyLength[1] = pMsg1->KeyDesc.KeyLength[1];
687
688 // 4. Fill SNonce
689 NdisMoveMemory(Packet.KeyDesc.KeyNonce, pAd->StaCfg.SNonce, LEN_KEY_DESC_NONCE);
690
691 // 5. Key Replay Count
692 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
693
694 // Convert to little-endian format.
695 *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
696
697 // Send EAPOL-Key(0,1,0,0,0,P,0,SNonce,MIC,RSN IE)
698 // Out buffer for transmitting message 2
699 MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory
700 if(pOutBuffer == NULL)
701 {
702 os_free_mem(pAd, mpool);
703 return;
704 }
705
706 // Prepare EAPOL frame for MIC calculation
707 // Be careful, only EAPOL frame is counted for MIC calculation
708 MakeOutgoingFrame(pOutBuffer, &FrameLen,
709 Packet.Body_Len[1] + 4, &Packet,
710 END_OF_ARGS);
711
712 // 6. Prepare and Fill MIC value
713 NdisZeroMemory(Mic, sizeof(Mic));
714 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
715 {
716 // AES
717 HMAC_SHA1(pOutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
718 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
719 }
720 else
721 {
722 hmac_md5(PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
723 }
724 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
725
726
727 // Make Transmitting frame
728 MakeOutgoingFrame(pOutBuffer, &FrameLen,
729 LENGTH_802_3, &Header802_3,
730 Packet.Body_Len[1] + 4, &Packet,
731 END_OF_ARGS);
732
733
734 // 5. Copy frame to Tx ring
735 RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
736
737 MlmeFreeMemory(pAd, pOutBuffer);
738 os_free_mem(pAd, mpool);
739
740 DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg1Action <-----\n"));
741
742}
743
744/*
745 ========================================================================
746
747 Routine Description:
748 Process Pairwise key 4-way handshaking
749
750 Arguments:
751 pAd Pointer to our adapter
752 Elem Message body
753
754 Return Value:
755 None
756
757 Note:
758
759 ========================================================================
760*/
761VOID WpaPairMsg3Action(
762 IN PRTMP_ADAPTER pAd,
763 IN MLME_QUEUE_ELEM *Elem)
764
765{
766 PHEADER_802_11 pHeader;
767 PUCHAR pOutBuffer = NULL;
768 UCHAR Header802_3[14];
769 ULONG FrameLen = 0;
770 EAPOL_PACKET Packet;
771 PEAPOL_PACKET pMsg3;
772 UCHAR Mic[16], OldMic[16];
773 MAC_TABLE_ENTRY *pEntry = NULL;
774 UCHAR skip_offset;
775 KEY_INFO peerKeyInfo;
776
777 DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action ----->\n"));
778
779 // Record 802.11 header & the received EAPOL packet Msg3
780 pHeader = (PHEADER_802_11) Elem->Msg;
781 pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
782
783 NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
784 NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO));
785
786 *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo));
787
788
789 // 1. Verify cipher type match
790 if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2))
791 {
792 return;
793 }
794 else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1))
795 {
796 return;
797 }
798
799 // Verify RSN IE
800 //if (!RTMPEqualMemory(pMsg3->KeyDesc.KeyData, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len))
801 if (!CheckRSNIE(pAd, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1], &skip_offset))
802 {
803 DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in Msg 3 of WPA1 4-way handshake!! \n"));
804 hex_dump("The original RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len);
805 hex_dump("The received RSN_IE", pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]);
806 return;
807 }
808 else
809 DBGPRINT(RT_DEBUG_TRACE, ("RSN_IE VALID in Msg 3 of WPA1 4-way handshake!! \n"));
810
811
812 // 2. Check MIC value
813 // Save the MIC and replace with zero
814 NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
815 NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
816 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
817 {
818 // AES
819 UCHAR digest[80];
820
821 HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
822 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
823 }
824 else // TKIP
825 {
826 hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic);
827 }
828
829 if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
830 {
831 DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n"));
832 return;
833 }
834 else
835 DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n"));
836
837 // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger
838 if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
839 return;
840
841 // Update new replay counter
842 NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
843
844 // 4. Double check ANonce
845 if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
846 return;
847
848 // init 802.3 header and Fill Packet
849 MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
850
851 // Zero Message 4 body
852 NdisZeroMemory(&Packet, sizeof(Packet));
853 Packet.ProVer = EAPOL_VER;
854 Packet.ProType = EAPOLKey;
855 Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field
856
857 //
858 // Message 4 as EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0)
859 //
860 Packet.KeyDesc.Type = WPA1_KEY_DESC;
861
862 // Key descriptor version and appropriate RSN IE
863 Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer;
864
865 // Update Key Length
866 Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0];
867 Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1];
868
869 // Key Type PeerKey
870 Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
871
872 // KeyMic field presented
873 Packet.KeyDesc.KeyInfo.KeyMic = 1;
874
875 // In Msg3, KeyInfo.secure =0 if Group Key HS to come. 1 if no group key HS
876 // Station sends Msg4 KeyInfo.secure should be the same as that in Msg.3
877 Packet.KeyDesc.KeyInfo.Secure= peerKeyInfo.Secure;
878
879 // Convert to little-endian format.
880 *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
881
882 // Key Replay count
883 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
884
885 // Out buffer for transmitting message 4
886 MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory
887 if(pOutBuffer == NULL)
888 return;
889
890 // Prepare EAPOL frame for MIC calculation
891 // Be careful, only EAPOL frame is counted for MIC calculation
892 MakeOutgoingFrame(pOutBuffer, &FrameLen,
893 Packet.Body_Len[1] + 4, &Packet,
894 END_OF_ARGS);
895
896 // Prepare and Fill MIC value
897 NdisZeroMemory(Mic, sizeof(Mic));
898 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
899 {
900 // AES
901 UCHAR digest[80];
902
903 HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
904 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
905 }
906 else
907 {
908 hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
909 }
910 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
911
912 // Update PTK
913 // Prepare pair-wise key information into shared key table
914 NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
915 pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
916 NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
917 NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
918 NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
919
920 // Decide its ChiperAlg
921 if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
922 pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
923 else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
924 pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
925 else
926 pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE;
927
928 // Update these related information to MAC_TABLE_ENTRY
929 pEntry = &pAd->MacTab.Content[BSSID_WCID];
930 NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
931 NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
932 NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
933 pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
934
935 // Update pairwise key information to ASIC Shared Key Table
936 AsicAddSharedKeyEntry(pAd,
937 BSS0,
938 0,
939 pAd->SharedKey[BSS0][0].CipherAlg,
940 pAd->SharedKey[BSS0][0].Key,
941 pAd->SharedKey[BSS0][0].TxMic,
942 pAd->SharedKey[BSS0][0].RxMic);
943
944 // Update ASIC WCID attribute table and IVEIV table
945 RTMPAddWcidAttributeEntry(pAd,
946 BSS0,
947 0,
948 pAd->SharedKey[BSS0][0].CipherAlg,
949 pEntry);
950
951 // Make transmitting frame
952 MakeOutgoingFrame(pOutBuffer, &FrameLen,
953 LENGTH_802_3, &Header802_3,
954 Packet.Body_Len[1] + 4, &Packet,
955 END_OF_ARGS);
956
957
958 // Copy frame to Tx ring and Send Message 4 to authenticator
959 RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
960
961 MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
962
963 DBGPRINT(RT_DEBUG_TRACE, ("WpaPairMsg3Action <-----\n"));
964}
965
966VOID Wpa2PairMsg3Action(
967 IN PRTMP_ADAPTER pAd,
968 IN MLME_QUEUE_ELEM *Elem)
969
970{
971 PHEADER_802_11 pHeader;
972 PUCHAR pOutBuffer = NULL;
973 UCHAR Header802_3[14];
974 ULONG FrameLen = 0;
975 EAPOL_PACKET Packet;
976 PEAPOL_PACKET pMsg3;
977 UCHAR Mic[16], OldMic[16];
978 UCHAR *mpool, *KEYDATA, *digest;
979 UCHAR Key[32];
980 MAC_TABLE_ENTRY *pEntry = NULL;
981 KEY_INFO peerKeyInfo;
982
983 // allocate memory
984 os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024);
985
986 if(mpool == NULL)
987 return;
988
989 // KEYDATA Len = 512.
990 KEYDATA = (UCHAR *) ROUND_UP(mpool, 4);
991 // digest Len = 80.
992 digest = (UCHAR *) ROUND_UP(KEYDATA + 512, 4);
993
994 DBGPRINT(RT_DEBUG_TRACE, ("Wpa2PairMsg3Action ----->\n"));
995
996 pHeader = (PHEADER_802_11) Elem->Msg;
997
998 // Process message 3 frame.
999 pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
1000
1001 NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
1002 NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pMsg3->KeyDesc.KeyInfo, sizeof(KEY_INFO));
1003
1004 *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo));
1005
1006 // 1. Verify cipher type match
1007 if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer!= 2))
1008 {
1009 os_free_mem(pAd, (PUCHAR)mpool);
1010 return;
1011 }
1012 else if(pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1))
1013 {
1014 os_free_mem(pAd, (PUCHAR)mpool);
1015 return;
1016 }
1017
1018 // 2. Check MIC value
1019 // Save the MIC and replace with zero
1020 NdisMoveMemory(OldMic, pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1021 NdisZeroMemory(pMsg3->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1022 if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1023 {
1024 // AES
1025 HMAC_SHA1((PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
1026 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
1027 }
1028 else
1029 {
1030 hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pMsg3, pMsg3->Body_Len[1] + 4, Mic);
1031 }
1032
1033 if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
1034 {
1035 DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in msg 3 of 4-way handshake!!!!!!!!!! \n"));
1036 os_free_mem(pAd, (PUCHAR)mpool);
1037 return;
1038 }
1039 else
1040 DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in msg 3 of 4-way handshake!!!!!!!!!! \n"));
1041
1042 // 3. Check Replay Counter, it has to be larger than last one. No need to be exact one larger
1043 if(RTMPCompareMemory(pMsg3->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
1044 {
1045 os_free_mem(pAd, (PUCHAR)mpool);
1046 return;
1047 }
1048
1049 // Update new replay counter
1050 NdisMoveMemory(pAd->StaCfg.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1051
1052 // 4. Double check ANonce
1053 if(!NdisEqualMemory(pAd->StaCfg.ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
1054 {
1055 os_free_mem(pAd, (PUCHAR)mpool);
1056 return;
1057 }
1058
1059 // Obtain GTK
1060 // 5. Decrypt GTK from Key Data
1061 DBGPRINT_RAW(RT_DEBUG_TRACE, ("EKD = %d\n", peerKeyInfo.EKD_DL));
1062 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1063 {
1064 // Decrypt AES GTK
1065 AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA, pMsg3->KeyDesc.KeyDataLen[1],pMsg3->KeyDesc.KeyData);
1066 }
1067 else // TKIP
1068 {
1069 INT i;
1070 // Decrypt TKIP GTK
1071 // Construct 32 bytes RC4 Key
1072 NdisMoveMemory(Key, pMsg3->KeyDesc.KeyIv, 16);
1073 NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16);
1074 ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32);
1075 //discard first 256 bytes
1076 for(i = 0; i < 256; i++)
1077 ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT);
1078 // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
1079 ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pMsg3->KeyDesc.KeyData, pMsg3->KeyDesc.KeyDataLen[1]);
1080 }
1081
1082 if (!ParseKeyData(pAd, KEYDATA, pMsg3->KeyDesc.KeyDataLen[1], 1))
1083 {
1084 os_free_mem(pAd, (PUCHAR)mpool);
1085 return;
1086 }
1087
1088 // Update GTK to ASIC
1089 // Update group key information to ASIC Shared Key Table
1090 AsicAddSharedKeyEntry(pAd,
1091 BSS0,
1092 pAd->StaCfg.DefaultKeyId,
1093 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
1094 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
1095 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic,
1096 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic);
1097
1098 // Update ASIC WCID attribute table and IVEIV table
1099 RTMPAddWcidAttributeEntry(pAd,
1100 BSS0,
1101 pAd->StaCfg.DefaultKeyId,
1102 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
1103 NULL);
1104
1105 // init 802.3 header and Fill Packet
1106 MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
1107
1108 // Zero message 4 body
1109 NdisZeroMemory(&Packet, sizeof(Packet));
1110 Packet.ProVer = EAPOL_VER;
1111 Packet.ProType = EAPOLKey;
1112 Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field
1113
1114 //
1115 // Message 4 as EAPOL-Key(0,1,0,0,0,P,0,0,MIC,0)
1116 //
1117 Packet.KeyDesc.Type = WPA2_KEY_DESC;
1118
1119 // Key descriptor version and appropriate RSN IE
1120 Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer;
1121
1122 // Update Key Length
1123 Packet.KeyDesc.KeyLength[0] = pMsg3->KeyDesc.KeyLength[0];
1124 Packet.KeyDesc.KeyLength[1] = pMsg3->KeyDesc.KeyLength[1];
1125
1126 // Key Type PeerKey
1127 Packet.KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
1128
1129 // KeyMic field presented
1130 Packet.KeyDesc.KeyInfo.KeyMic = 1;
1131 Packet.KeyDesc.KeyInfo.Secure = 1;
1132
1133 // Convert to little-endian format.
1134 *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
1135
1136 // Key Replay count
1137 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1138
1139 // Out buffer for transmitting message 4
1140 MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory
1141 if(pOutBuffer == NULL)
1142 {
1143 os_free_mem(pAd, (PUCHAR)mpool);
1144 return;
1145 }
1146
1147 // Prepare EAPOL frame for MIC calculation
1148 // Be careful, only EAPOL frame is counted for MIC calculation
1149 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1150 Packet.Body_Len[1] + 4, &Packet,
1151 END_OF_ARGS);
1152
1153 // Prepare and Fill MIC value
1154 NdisZeroMemory(Mic, sizeof(Mic));
1155 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1156 {
1157 // AES
1158 HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
1159 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
1160 }
1161 else
1162 {
1163 hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
1164 }
1165 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
1166
1167 // Update PTK
1168 // Prepare pair-wise key information into shared key table
1169 NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
1170 pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
1171 NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
1172 NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
1173 NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
1174
1175 // Decide its ChiperAlg
1176 if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
1177 pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
1178 else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
1179 pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
1180 else
1181 pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_NONE;
1182
1183 // Update these related information to MAC_TABLE_ENTRY
1184 pEntry = &pAd->MacTab.Content[BSSID_WCID];
1185 NdisMoveMemory(&pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
1186 NdisMoveMemory(&pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
1187 NdisMoveMemory(&pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
1188 pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
1189
1190 // Update pairwise key information to ASIC Shared Key Table
1191 AsicAddSharedKeyEntry(pAd,
1192 BSS0,
1193 0,
1194 pAd->SharedKey[BSS0][0].CipherAlg,
1195 pAd->SharedKey[BSS0][0].Key,
1196 pAd->SharedKey[BSS0][0].TxMic,
1197 pAd->SharedKey[BSS0][0].RxMic);
1198
1199 // Update ASIC WCID attribute table and IVEIV table
1200 RTMPAddWcidAttributeEntry(pAd,
1201 BSS0,
1202 0,
1203 pAd->SharedKey[BSS0][0].CipherAlg,
1204 pEntry);
1205
1206 // Make Transmitting frame
1207 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1208 LENGTH_802_3, &Header802_3,
1209 Packet.Body_Len[1] + 4, &Packet,
1210 END_OF_ARGS);
1211
1212
1213 // Copy frame to Tx ring and Send Message 4 to authenticator
1214 RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, TRUE);
1215
1216 // set 802.1x port control
1217 STA_PORT_SECURED(pAd);
1218
1219 // Indicate Connected for GUI
1220 pAd->IndicateMediaState = NdisMediaStateConnected;
1221
1222 MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
1223 os_free_mem(pAd, (PUCHAR)mpool);
1224
1225
1226 // send wireless event - for set key done WPA2
1227 if (pAd->CommonCfg.bWirelessEvent)
1228 RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, BSS0, 0);
1229
1230 DBGPRINT(RT_DEBUG_ERROR, ("Wpa2PairMsg3Action <-----\n"));
1231
1232}
1233
1234/*
1235 ========================================================================
1236
1237 Routine Description:
1238 Process Group key 2-way handshaking
1239
1240 Arguments:
1241 pAd Pointer to our adapter
1242 Elem Message body
1243
1244 Return Value:
1245 None
1246
1247 Note:
1248
1249 ========================================================================
1250*/
1251VOID WpaGroupMsg1Action(
1252 IN PRTMP_ADAPTER pAd,
1253 IN MLME_QUEUE_ELEM *Elem)
1254
1255{
1256 PUCHAR pOutBuffer = NULL;
1257 UCHAR Header802_3[14];
1258 ULONG FrameLen = 0;
1259 EAPOL_PACKET Packet;
1260 PEAPOL_PACKET pGroup;
1261 UCHAR *mpool, *digest, *KEYDATA;
1262 UCHAR Mic[16], OldMic[16];
1263 UCHAR GTK[32], Key[32];
1264 KEY_INFO peerKeyInfo;
1265
1266 // allocate memory
1267 os_alloc_mem(pAd, (PUCHAR *)&mpool, 1024);
1268
1269 if(mpool == NULL)
1270 return;
1271
1272 // digest Len = 80.
1273 digest = (UCHAR *) ROUND_UP(mpool, 4);
1274 // KEYDATA Len = 512.
1275 KEYDATA = (UCHAR *) ROUND_UP(digest + 80, 4);
1276
1277 DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action ----->\n"));
1278
1279 // Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8)
1280 pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
1281
1282 NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
1283 NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pGroup->KeyDesc.KeyInfo, sizeof(KEY_INFO));
1284
1285 *((USHORT*)&peerKeyInfo) = cpu2le16(*((USHORT*)&peerKeyInfo));
1286
1287 // 0. Check cipher type match
1288 if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled && (peerKeyInfo.KeyDescVer != 2))
1289 {
1290 os_free_mem(pAd, (PUCHAR)mpool);
1291 return;
1292 }
1293 else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled && (peerKeyInfo.KeyDescVer != 1))
1294 {
1295 os_free_mem(pAd, (PUCHAR)mpool);
1296 return;
1297 }
1298
1299 // 1. Verify Replay counter
1300 // Check Replay Counter, it has to be larger than last one. No need to be exact one larger
1301 if(RTMPCompareMemory(pGroup->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1)
1302 {
1303 os_free_mem(pAd, (PUCHAR)mpool);
1304 return;
1305 }
1306
1307 // Update new replay counter
1308 NdisMoveMemory(pAd->StaCfg.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1309
1310 // 2. Verify MIC is valid
1311 // Save the MIC and replace with zero
1312 NdisMoveMemory(OldMic, pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1313 NdisZeroMemory(pGroup->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
1314
1315 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1316 { // AES
1317 HMAC_SHA1((PUCHAR) pGroup, pGroup->Body_Len[1] + 4, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
1318 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
1319 }
1320 else
1321 { // TKIP
1322 hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, (PUCHAR) pGroup, pGroup->Body_Len[1] + 4, Mic);
1323 }
1324
1325 if(!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
1326 {
1327 DBGPRINT(RT_DEBUG_ERROR, (" MIC Different in group msg 1 of 2-way handshake!!!!!!!!!! \n"));
1328 MlmeFreeMemory(pAd, (PUCHAR)mpool);
1329 return;
1330 }
1331 else
1332 DBGPRINT(RT_DEBUG_TRACE, (" MIC VALID in group msg 1 of 2-way handshake!!!!!!!!!! \n"));
1333
1334
1335 // 3. Decrypt GTK from Key Data
1336 if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1337 {
1338 // Decrypt AES GTK
1339 AES_GTK_KEY_UNWRAP(&pAd->StaCfg.PTK[16], KEYDATA, pGroup->KeyDesc.KeyDataLen[1], pGroup->KeyDesc.KeyData);
1340 }
1341 else // TKIP
1342 {
1343 INT i;
1344
1345 // Decrypt TKIP GTK
1346 // Construct 32 bytes RC4 Key
1347 NdisMoveMemory(Key, pGroup->KeyDesc.KeyIv, 16);
1348 NdisMoveMemory(&Key[16], &pAd->StaCfg.PTK[16], 16);
1349 ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32);
1350 //discard first 256 bytes
1351 for(i = 0; i < 256; i++)
1352 ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT);
1353 // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
1354 ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pGroup->KeyDesc.KeyData, pGroup->KeyDesc.KeyDataLen[1]);
1355 }
1356
1357 // Process decrypted key data material
1358 // Parse keyData to handle KDE format for WPA2PSK
1359 if (peerKeyInfo.EKD_DL)
1360 {
1361 if (!ParseKeyData(pAd, KEYDATA, pGroup->KeyDesc.KeyDataLen[1], 0))
1362 {
1363 os_free_mem(pAd, (PUCHAR)mpool);
1364 return;
1365 }
1366 }
1367 else // WPAPSK
1368 {
1369 // set key material, TxMic and RxMic for WPAPSK
1370 NdisMoveMemory(GTK, KEYDATA, 32);
1371 NdisMoveMemory(pAd->StaCfg.GTK, GTK, 32);
1372 pAd->StaCfg.DefaultKeyId = peerKeyInfo.KeyIndex;
1373
1374 // Prepare pair-wise key information into shared key table
1375 NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY));
1376 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK;
1377 NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, GTK, LEN_TKIP_EK);
1378 NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, &GTK[16], LEN_TKIP_RXMICK);
1379 NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, &GTK[24], LEN_TKIP_TXMICK);
1380
1381 // Update Shared Key CipherAlg
1382 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE;
1383 if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
1384 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP;
1385 else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
1386 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES;
1387#ifndef RT30xx
1388 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
1389 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP64;
1390 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
1391 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP128;
1392#endif
1393
1394 //hex_dump("Group Key :", pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, LEN_TKIP_EK);
1395 }
1396
1397 // Update group key information to ASIC Shared Key Table
1398 AsicAddSharedKeyEntry(pAd,
1399 BSS0,
1400 pAd->StaCfg.DefaultKeyId,
1401 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
1402 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
1403 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic,
1404 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic);
1405
1406 // Update ASIC WCID attribute table and IVEIV table
1407 RTMPAddWcidAttributeEntry(pAd,
1408 BSS0,
1409 pAd->StaCfg.DefaultKeyId,
1410 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
1411 NULL);
1412
1413 // set 802.1x port control
1414 STA_PORT_SECURED(pAd);
1415
1416 // Indicate Connected for GUI
1417 pAd->IndicateMediaState = NdisMediaStateConnected;
1418
1419 // init header and Fill Packet
1420 MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
1421
1422 // Zero Group message 1 body
1423 NdisZeroMemory(&Packet, sizeof(Packet));
1424 Packet.ProVer = EAPOL_VER;
1425 Packet.ProType = EAPOLKey;
1426 Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE; // No data field
1427
1428 //
1429 // Group Message 2 as EAPOL-Key(1,0,0,0,G,0,0,MIC,0)
1430 //
1431 if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
1432 {
1433 Packet.KeyDesc.Type = WPA2_KEY_DESC;
1434 }
1435 else
1436 {
1437 Packet.KeyDesc.Type = WPA1_KEY_DESC;
1438 }
1439
1440 // Key descriptor version and appropriate RSN IE
1441 Packet.KeyDesc.KeyInfo.KeyDescVer = peerKeyInfo.KeyDescVer;
1442
1443 // Update Key Length
1444 Packet.KeyDesc.KeyLength[0] = pGroup->KeyDesc.KeyLength[0];
1445 Packet.KeyDesc.KeyLength[1] = pGroup->KeyDesc.KeyLength[1];
1446
1447 // Key Index as G-Msg 1
1448 if(pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
1449 Packet.KeyDesc.KeyInfo.KeyIndex = peerKeyInfo.KeyIndex;
1450
1451 // Key Type Group key
1452 Packet.KeyDesc.KeyInfo.KeyType = GROUPKEY;
1453
1454 // KeyMic field presented
1455 Packet.KeyDesc.KeyInfo.KeyMic = 1;
1456
1457 // Secure bit
1458 Packet.KeyDesc.KeyInfo.Secure = 1;
1459
1460 // Convert to little-endian format.
1461 *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
1462
1463 // Key Replay count
1464 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1465
1466 // Out buffer for transmitting group message 2
1467 MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory
1468 if(pOutBuffer == NULL)
1469 {
1470 MlmeFreeMemory(pAd, (PUCHAR)mpool);
1471 return;
1472 }
1473
1474 // Prepare EAPOL frame for MIC calculation
1475 // Be careful, only EAPOL frame is counted for MIC calculation
1476 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1477 Packet.Body_Len[1] + 4, &Packet,
1478 END_OF_ARGS);
1479
1480 // Prepare and Fill MIC value
1481 NdisZeroMemory(Mic, sizeof(Mic));
1482 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1483 {
1484 // AES
1485 HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
1486 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
1487 }
1488 else
1489 {
1490 hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
1491 }
1492 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
1493
1494
1495 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1496 LENGTH_802_3, &Header802_3,
1497 Packet.Body_Len[1] + 4, &Packet,
1498 END_OF_ARGS);
1499
1500
1501 // 5. Copy frame to Tx ring and prepare for encryption
1502 RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE);
1503
1504 // 6 Free allocated memory
1505 MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
1506 os_free_mem(pAd, (PUCHAR)mpool);
1507
1508 // send wireless event - for set key done WPA2
1509 if (pAd->CommonCfg.bWirelessEvent)
1510 RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1511
1512 DBGPRINT(RT_DEBUG_TRACE, ("WpaGroupMsg1Action <-----\n"));
1513}
1514
1515/*
1516 ========================================================================
1517
1518 Routine Description:
1519 Init WPA MAC header
1520
1521 Arguments:
1522 pAd Pointer to our adapter
1523
1524 Return Value:
1525 None
1526
1527 Note:
1528
1529 ========================================================================
1530*/
1531VOID WpaMacHeaderInit(
1532 IN PRTMP_ADAPTER pAd,
1533 IN OUT PHEADER_802_11 pHdr80211,
1534 IN UCHAR wep,
1535 IN PUCHAR pAddr1)
1536{
1537 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
1538 pHdr80211->FC.Type = BTYPE_DATA;
1539 pHdr80211->FC.ToDs = 1;
1540 if (wep == 1)
1541 pHdr80211->FC.Wep = 1;
1542
1543 // Addr1: BSSID, Addr2: SA, Addr3: DA
1544 COPY_MAC_ADDR(pHdr80211->Addr1, pAddr1);
1545 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
1546 COPY_MAC_ADDR(pHdr80211->Addr3, pAd->CommonCfg.Bssid);
1547 pHdr80211->Sequence = pAd->Sequence;
1548}
1549
1550/*
1551 ========================================================================
1552
1553 Routine Description:
1554 Copy frame from waiting queue into relative ring buffer and set
1555 appropriate ASIC register to kick hardware encryption before really
1556 sent out to air.
1557
1558 Arguments:
1559 pAd Pointer to our adapter
1560 PNDIS_PACKET Pointer to outgoing Ndis frame
1561 NumberOfFrag Number of fragment required
1562
1563 Return Value:
1564 None
1565
1566 Note:
1567
1568 ========================================================================
1569*/
1570VOID RTMPToWirelessSta(
1571 IN PRTMP_ADAPTER pAd,
1572 IN PUCHAR pHeader802_3,
1573 IN UINT HdrLen,
1574 IN PUCHAR pData,
1575 IN UINT DataLen,
1576 IN BOOLEAN is4wayFrame)
1577
1578{
1579 NDIS_STATUS Status;
1580 PNDIS_PACKET pPacket;
1581 UCHAR Index;
1582
1583 do
1584 {
1585 // 1. build a NDIS packet and call RTMPSendPacket();
1586 // be careful about how/when to release this internal allocated NDIS PACKET buffer
1587 Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen);
1588 if (Status != NDIS_STATUS_SUCCESS)
1589 break;
1590
1591 if (is4wayFrame)
1592 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
1593 else
1594 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
1595
1596 // 2. send out the packet
1597 Status = STASendPacket(pAd, pPacket);
1598 if(Status == NDIS_STATUS_SUCCESS)
1599 {
1600 // Dequeue one frame from TxSwQueue0..3 queue and process it
1601 // There are three place calling dequeue for TX ring.
1602 // 1. Here, right after queueing the frame.
1603 // 2. At the end of TxRingTxDone service routine.
1604 // 3. Upon NDIS call RTMPSendPackets
1605 if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1606 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)))
1607 {
1608 for(Index = 0; Index < 5; Index ++)
1609 if(pAd->TxSwQueue[Index].Number > 0)
1610 RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS);
1611 }
1612 }
1613 } while(FALSE);
1614
1615}
1616
1617/*
1618 ========================================================================
1619
1620 Routine Description:
1621 Check Sanity RSN IE form AP
1622
1623 Arguments:
1624
1625 Return Value:
1626
1627
1628 ========================================================================
1629*/
1630BOOLEAN CheckRSNIE(
1631 IN PRTMP_ADAPTER pAd,
1632 IN PUCHAR pData,
1633 IN UCHAR DataLen,
1634 OUT UCHAR *Offset)
1635{
1636 PUCHAR pVIE;
1637 UCHAR len;
1638 PEID_STRUCT pEid;
1639 BOOLEAN result = FALSE;
1640
1641 pVIE = pData;
1642 len = DataLen;
1643 *Offset = 0;
1644
1645 while (len > sizeof(RSNIE2))
1646 {
1647 pEid = (PEID_STRUCT) pVIE;
1648 // WPA RSN IE
1649 if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
1650 {
1651 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) &&
1652 (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) &&
1653 (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2)))
1654 {
1655 DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA/WPAPSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2)));
1656 result = TRUE;
1657 }
1658
1659 *Offset += (pEid->Len + 2);
1660 }
1661 // WPA2 RSN IE
1662 else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
1663 {
1664 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) &&
1665 (NdisEqualMemory(pVIE, pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len)) &&
1666 (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == (pEid->Len + 2)))
1667 {
1668 DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", (pEid->Len + 2)));
1669 result = TRUE;
1670 }
1671
1672 *Offset += (pEid->Len + 2);
1673 }
1674 else
1675 {
1676 break;
1677 }
1678
1679 pVIE += (pEid->Len + 2);
1680 len -= (pEid->Len + 2);
1681 }
1682
1683 DBGPRINT(RT_DEBUG_TRACE, ("CheckRSNIE ==> skip_offset(%d) \n", *Offset));
1684
1685 return result;
1686
1687}
1688
1689
1690/*
1691 ========================================================================
1692
1693 Routine Description:
1694 Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK.
1695 GTK is encaptulated in KDE format at p.83 802.11i D10
1696
1697 Arguments:
1698
1699 Return Value:
1700
1701 Note:
1702 802.11i D10
1703
1704 ========================================================================
1705*/
1706BOOLEAN ParseKeyData(
1707 IN PRTMP_ADAPTER pAd,
1708 IN PUCHAR pKeyData,
1709 IN UCHAR KeyDataLen,
1710 IN UCHAR bPairewise)
1711{
1712 PKDE_ENCAP pKDE = NULL;
1713 PUCHAR pMyKeyData = pKeyData;
1714 UCHAR KeyDataLength = KeyDataLen;
1715 UCHAR GTKLEN;
1716 UCHAR skip_offset;
1717
1718 // Verify The RSN IE contained in Pairewise-Msg 3 and skip it
1719 if (bPairewise)
1720 {
1721 // Check RSN IE whether it is WPA2/WPA2PSK
1722 if (!CheckRSNIE(pAd, pKeyData, KeyDataLen, &skip_offset))
1723 {
1724 DBGPRINT(RT_DEBUG_ERROR, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE mismatched \n"));
1725 hex_dump("Get KEYDATA :", pKeyData, KeyDataLen);
1726 return FALSE;
1727 }
1728 else
1729 {
1730 // skip RSN IE
1731 pMyKeyData += skip_offset;
1732 KeyDataLength -= skip_offset;
1733
1734 //DBGPRINT(RT_DEBUG_TRACE, ("ParseKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
1735 }
1736 }
1737
1738 DBGPRINT(RT_DEBUG_TRACE,("ParseKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
1739
1740 // Parse EKD format
1741 if (KeyDataLength >= 8)
1742 {
1743 pKDE = (PKDE_ENCAP) pMyKeyData;
1744 }
1745 else
1746 {
1747 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KeyDataLength is too short \n"));
1748 return FALSE;
1749 }
1750
1751
1752 // Sanity check - shared key index should not be 0
1753 if (pKDE->GTKEncap.Kid == 0)
1754 {
1755 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index zero \n"));
1756 return FALSE;
1757 }
1758
1759 // Sanity check - KED length
1760 if (KeyDataLength < (pKDE->Len + 2))
1761 {
1762 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
1763 return FALSE;
1764 }
1765
1766 // Get GTK length - refer to IEEE 802.11i-2004 p.82
1767 GTKLEN = pKDE->Len -6;
1768
1769#ifdef RT30xx
1770 if (GTKLEN < LEN_AES_KEY)
1771#endif
1772#ifndef RT30xx
1773 if (GTKLEN < MIN_LEN_OF_GTK)
1774#endif
1775 {
1776 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
1777 return FALSE;
1778 }
1779 else
1780 DBGPRINT(RT_DEBUG_TRACE, ("GTK Key with KDE formet got index=%d, len=%d \n", pKDE->GTKEncap.Kid, GTKLEN));
1781
1782 // Update GTK
1783 // set key material, TxMic and RxMic for WPAPSK
1784 NdisMoveMemory(pAd->StaCfg.GTK, pKDE->GTKEncap.GTK, 32);
1785 pAd->StaCfg.DefaultKeyId = pKDE->GTKEncap.Kid;
1786
1787 // Update shared key table
1788 NdisZeroMemory(&pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId], sizeof(CIPHER_KEY));
1789 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen = LEN_TKIP_EK;
1790 NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key, pKDE->GTKEncap.GTK, LEN_TKIP_EK);
1791 NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].RxMic, &pKDE->GTKEncap.GTK[16], LEN_TKIP_RXMICK);
1792 NdisMoveMemory(pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].TxMic, &pKDE->GTKEncap.GTK[24], LEN_TKIP_TXMICK);
1793
1794 // Update Shared Key CipherAlg
1795 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_NONE;
1796 if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
1797 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_TKIP;
1798 else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
1799 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_AES;
1800#ifndef RT30xx
1801 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
1802 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP64;
1803 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
1804 pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg = CIPHER_WEP128;
1805#endif
1806
1807 return TRUE;
1808
1809}
1810
1811/*
1812 ========================================================================
1813
1814 Routine Description:
1815 Cisco CCKM PRF function
1816
1817 Arguments:
1818 key Cisco Base Transient Key (BTK)
1819 key_len The key length of the BTK
1820 data Ruquest Number(RN) + BSSID
1821 data_len The length of the data
1822 output Store for PTK(Pairwise transient keys)
1823 len The length of the output
1824 Return Value:
1825 None
1826
1827 Note:
1828 802.1i Annex F.9
1829
1830 ========================================================================
1831*/
1832VOID CCKMPRF(
1833 IN UCHAR *key,
1834 IN INT key_len,
1835 IN UCHAR *data,
1836 IN INT data_len,
1837 OUT UCHAR *output,
1838 IN INT len)
1839{
1840 INT i;
1841 UCHAR input[1024];
1842 INT currentindex = 0;
1843 INT total_len;
1844
1845 NdisMoveMemory(input, data, data_len);
1846 total_len = data_len;
1847 input[total_len] = 0;
1848 total_len++;
1849 for (i = 0; i < (len + 19) / 20; i++)
1850 {
1851 HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]);
1852 currentindex += 20;
1853 input[total_len - 1]++;
1854 }
1855}
1856
1857/*
1858 ========================================================================
1859
1860 Routine Description:
1861 Process MIC error indication and record MIC error timer.
1862
1863 Arguments:
1864 pAd Pointer to our adapter
1865 pWpaKey Pointer to the WPA key structure
1866
1867 Return Value:
1868 None
1869
1870 IRQL = DISPATCH_LEVEL
1871
1872 Note:
1873
1874 ========================================================================
1875*/
1876VOID RTMPReportMicError(
1877 IN PRTMP_ADAPTER pAd,
1878 IN PCIPHER_KEY pWpaKey)
1879{
1880 ULONG Now;
1881 UCHAR unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0);
1882
1883 // Record Last MIC error time and count
1884 Now = jiffies;
1885 if (pAd->StaCfg.MicErrCnt == 0)
1886 {
1887 pAd->StaCfg.MicErrCnt++;
1888 pAd->StaCfg.LastMicErrorTime = Now;
1889 NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
1890 }
1891 else if (pAd->StaCfg.MicErrCnt == 1)
1892 {
1893 if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now)
1894 {
1895 // Update Last MIC error time, this did not violate two MIC errors within 60 seconds
1896 pAd->StaCfg.LastMicErrorTime = Now;
1897 }
1898 else
1899 {
1900
1901 if (pAd->CommonCfg.bWirelessEvent)
1902 RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1903
1904 pAd->StaCfg.LastMicErrorTime = Now;
1905 // Violate MIC error counts, MIC countermeasures kicks in
1906 pAd->StaCfg.MicErrCnt++;
1907 }
1908 }
1909 else
1910 {
1911 // MIC error count >= 2
1912 // This should not happen
1913 ;
1914 }
1915 MlmeEnqueue(pAd,
1916 MLME_CNTL_STATE_MACHINE,
1917 OID_802_11_MIC_FAILURE_REPORT_FRAME,
1918 1,
1919 &unicastKey);
1920
1921 if (pAd->StaCfg.MicErrCnt == 2)
1922 {
1923 RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100);
1924 }
1925}
1926
1927#define LENGTH_EAP_H 4
1928// If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)).
1929INT WpaCheckEapCode(
1930 IN PRTMP_ADAPTER pAd,
1931 IN PUCHAR pFrame,
1932 IN USHORT FrameLen,
1933 IN USHORT OffSet)
1934{
1935
1936 PUCHAR pData;
1937 INT result = 0;
1938
1939 if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H )
1940 return result;
1941
1942 pData = pFrame + OffSet; // skip offset bytes
1943
1944 if(*(pData+1) == EAPPacket) // 802.1x header - Packet Type
1945 {
1946 result = *(pData+4); // EAP header - Code
1947 }
1948
1949 return result;
1950}
1951
1952VOID WpaSendMicFailureToWpaSupplicant(
1953 IN PRTMP_ADAPTER pAd,
1954 IN BOOLEAN bUnicast)
1955{
1956 union iwreq_data wrqu;
1957 char custom[IW_CUSTOM_MAX] = {0};
1958
1959 sprintf(custom, "MLME-MICHAELMICFAILURE.indication");
1960 if (bUnicast)
1961 sprintf(custom, "%s unicast", custom);
1962 wrqu.data.length = strlen(custom);
1963 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom);
1964
1965 return;
1966}
1967
1968VOID WpaMicFailureReportFrame(
1969 IN PRTMP_ADAPTER pAd,
1970 IN MLME_QUEUE_ELEM *Elem)
1971{
1972 PUCHAR pOutBuffer = NULL;
1973 UCHAR Header802_3[14];
1974 ULONG FrameLen = 0;
1975 EAPOL_PACKET Packet;
1976 UCHAR Mic[16];
1977 BOOLEAN bUnicast;
1978
1979 DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n"));
1980
1981 bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE);
1982 pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
1983
1984 // init 802.3 header and Fill Packet
1985 MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
1986
1987 NdisZeroMemory(&Packet, sizeof(Packet));
1988 Packet.ProVer = EAPOL_VER;
1989 Packet.ProType = EAPOLKey;
1990
1991 Packet.KeyDesc.Type = WPA1_KEY_DESC;
1992
1993 // Request field presented
1994 Packet.KeyDesc.KeyInfo.Request = 1;
1995
1996 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
1997 {
1998 Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
1999 }
2000 else // TKIP
2001 {
2002 Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
2003 }
2004
2005 Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY);
2006
2007 // KeyMic field presented
2008 Packet.KeyDesc.KeyInfo.KeyMic = 1;
2009
2010 // Error field presented
2011 Packet.KeyDesc.KeyInfo.Error = 1;
2012
2013 // Update packet length after decide Key data payload
2014 Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE;
2015
2016 // Key Replay Count
2017 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
2018 inc_byte_array(pAd->StaCfg.ReplayCounter, 8);
2019
2020 // Convert to little-endian format.
2021 *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
2022
2023
2024 MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory
2025 if(pOutBuffer == NULL)
2026 {
2027 return;
2028 }
2029
2030 // Prepare EAPOL frame for MIC calculation
2031 // Be careful, only EAPOL frame is counted for MIC calculation
2032 MakeOutgoingFrame(pOutBuffer, &FrameLen,
2033 Packet.Body_Len[1] + 4, &Packet,
2034 END_OF_ARGS);
2035
2036 // Prepare and Fill MIC value
2037 NdisZeroMemory(Mic, sizeof(Mic));
2038 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
2039 { // AES
2040 UCHAR digest[20] = {0};
2041 HMAC_SHA1(pOutBuffer, FrameLen, pAd->StaCfg.PTK, LEN_EAP_MICK, digest);
2042 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
2043 }
2044 else
2045 { // TKIP
2046 hmac_md5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
2047 }
2048 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
2049
2050 MakeOutgoingFrame(pOutBuffer, &FrameLen,
2051 LENGTH_802_3, &Header802_3,
2052 Packet.Body_Len[1] + 4, &Packet,
2053 END_OF_ARGS);
2054
2055 // opy frame to Tx ring and send MIC failure report frame to authenticator
2056 RTMPToWirelessSta(pAd, Header802_3, LENGTH_802_3, (PUCHAR)&Packet, Packet.Body_Len[1] + 4, FALSE);
2057
2058 MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
2059
2060 DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n"));
2061}
2062
2063/** from wpa_supplicant
2064 * inc_byte_array - Increment arbitrary length byte array by one
2065 * @counter: Pointer to byte array
2066 * @len: Length of the counter in bytes
2067 *
2068 * This function increments the last byte of the counter by one and continues
2069 * rolling over to more significant bytes if the byte was incremented from
2070 * 0xff to 0x00.
2071 */
2072void inc_byte_array(UCHAR *counter, int len)
2073{
2074 int pos = len - 1;
2075 while (pos >= 0) {
2076 counter[pos]++;
2077 if (counter[pos] != 0)
2078 break;
2079 pos--;
2080 }
2081}
2082
2083VOID WpaDisassocApAndBlockAssoc(
2084 IN PVOID SystemSpecific1,
2085 IN PVOID FunctionContext,
2086 IN PVOID SystemSpecific2,
2087 IN PVOID SystemSpecific3)
2088{
2089 RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext;
2090 MLME_DISASSOC_REQ_STRUCT DisassocReq;
2091
2092 // disassoc from current AP first
2093 DBGPRINT(RT_DEBUG_TRACE, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n"));
2094 DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_MIC_FAILURE);
2095 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
2096
2097 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
2098 pAd->StaCfg.bBlockAssoc = TRUE;
2099}
2100