added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / staging / rt2870 / sta / aironet.c
blob4af4a1906181133a98dc751c56d5c1ed9064b470
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
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 *************************************************************************
27 Module Name:
28 aironet.c
30 Abstract:
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 Paul Lin 04-06-15 Initial
37 #include "../rt_config.h"
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 ==========================================================================
47 VOID AironetStateMachineInit(
48 IN PRTMP_ADAPTER pAd,
49 IN STATE_MACHINE *S,
50 OUT STATE_MACHINE_FUNC Trans[])
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);
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 ==========================================================================
71 VOID AironetMsgAction(
72 IN PRTMP_ADAPTER pAd,
73 IN MLME_QUEUE_ELEM *Elem)
75 USHORT Length;
76 UCHAR Index, i;
77 PUCHAR pData;
78 PAIRONET_RM_REQUEST_FRAME pRMReq;
79 PRM_REQUEST_ACTION pReqElem;
81 DBGPRINT(RT_DEBUG_TRACE, ("-----> AironetMsgAction\n"));
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];
87 // 1. Change endian format form network to little endian
88 Length = be2cpu16(pRMReq->IAPP.Length);
90 // 2.0 Sanity check, this should only happen when CCX 2.0 support is enabled
91 if (pAd->StaCfg.CCXEnable != TRUE)
92 return;
94 // 2.1 Radio measurement must be on
95 if (pAd->StaCfg.CCXControl.field.RMEnable != 1)
96 return;
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));
106 // 3. Check IAPP frame type, it must be 0x32 for Cisco Aironet extension
107 if (pRMReq->IAPP.Type != AIRONET_IAPP_TYPE)
109 DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP type for Cisco Aironet extension\n"));
110 return;
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)
117 DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP subtype for Cisco Aironet extension\n"));
118 return;
121 // 5. Verify Destination MAC and Source MAC, both should be all zeros.
122 if (! MAC_ADDR_EQUAL(pRMReq->IAPP.DA, ZERO_MAC_ADDR))
124 DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP DA for Cisco Aironet extension, it's not Zero\n"));
125 return;
128 if (! MAC_ADDR_EQUAL(pRMReq->IAPP.SA, ZERO_MAC_ADDR))
130 DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP SA for Cisco Aironet extension, it's not Zero\n"));
131 return;
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);
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;
154 Index = 0;
156 // 8. Save dialog token for report
157 pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token;
159 // Save Activation delay & measurement offset, Not really needed
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);
166 // 10. Start Parsing the Measurement elements.
167 // Be careful about multiple MR elements within one frames.
168 while (Length > 0)
170 pReqElem = (PRM_REQUEST_ACTION) pData;
171 switch (pReqElem->ReqElem.Eid)
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.
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)
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)
194 // Check channel before enqueue the action
195 if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel)
196 break;
198 else
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;
206 // Save requests and execute actions later
207 NdisMoveMemory(&pAd->StaCfg.MeasurementRequest[Index], pReqElem, sizeof(RM_REQUEST_ACTION));
208 Index += 1;
209 break;
211 case MSRN_TYPE_FRAME_REQ:
212 // Since it's option, we will support later
213 // FrameRequestAction(pAd, pData);
214 break;
216 default:
217 break;
220 // Point to next Measurement request
221 pData += sizeof(RM_REQUEST_ACTION);
222 Length -= sizeof(RM_REQUEST_ACTION);
223 break;
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;
234 // 11. Update some flags and index
235 pAd->StaCfg.RMReqCnt = Index;
237 if (Index)
239 MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL);
240 RT28XX_MLME_HANDLER(pAd);
243 DBGPRINT(RT_DEBUG_TRACE, ("<----- AironetMsgAction\n"));
247 ========================================================================
249 Routine Description:
251 Arguments:
253 Return Value:
254 None
256 Note:
258 ========================================================================
260 VOID AironetRequestAction(
261 IN PRTMP_ADAPTER pAd,
262 IN MLME_QUEUE_ELEM *Elem)
264 PRM_REQUEST_ACTION pReq;
266 // 1. Point to next request element
267 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
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;
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)
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))
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));
297 // 4. Call RT28XX_MLME_HANDLER to execute the request mlme commands, Scan request is the only one used
298 RT28XX_MLME_HANDLER(pAd);
304 ========================================================================
306 Routine Description:
307 Prepare channel load report action, special scan operation added
308 to support
310 Arguments:
311 pAd Pointer to our adapter
312 pData Start from element ID
314 Return Value:
315 None
317 Note:
319 ========================================================================
321 VOID ChannelLoadRequestAction(
322 IN PRTMP_ADAPTER pAd,
323 IN UCHAR Index)
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;
332 DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction ----->\n"));
334 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
335 NdisZeroMemory(ZeroSsid, 32);
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
345 // Control state machine is not idle, reject the request
346 if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
347 return;
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;
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;
360 DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel));
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)
365 // Use MLME enqueue method
366 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
367 if (NStatus != NDIS_STATUS_SUCCESS)
368 return;
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;
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);
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);
389 // Set channel load measurement flag
390 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
392 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
394 DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction <-----\n"));
398 ========================================================================
400 Routine Description:
401 Prepare noise histogram report action, special scan operation added
402 to support
404 Arguments:
405 pAd Pointer to our adapter
406 pData Start from element ID
408 Return Value:
409 None
411 Note:
413 ========================================================================
415 VOID NoiseHistRequestAction(
416 IN PRTMP_ADAPTER pAd,
417 IN UCHAR Index)
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;
426 DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction ----->\n"));
428 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
429 NdisZeroMemory(ZeroSsid, 32);
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
439 // Control state machine is not idle, reject the request
440 if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
441 return;
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;
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;
455 DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel));
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)
460 // Use MLME enqueue method
461 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
462 if (NStatus != NDIS_STATUS_SUCCESS)
463 return;
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;
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);
479 // Reset the statistics
480 for (i = 0; i < 8; i++)
481 pAd->StaCfg.RPIDensity[i] = 0;
483 // Enable Rx with promiscuous reception
484 RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010);
486 // Set channel load measurement flag
487 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
489 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
491 DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction <-----\n"));
495 ========================================================================
497 Routine Description:
498 Prepare Beacon report action, special scan operation added
499 to support
501 Arguments:
502 pAd Pointer to our adapter
503 pData Start from element ID
505 Return Value:
506 None
508 Note:
510 ========================================================================
512 VOID BeaconRequestAction(
513 IN PRTMP_ADAPTER pAd,
514 IN UCHAR Index)
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];
523 DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction ----->\n"));
525 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
526 NdisZeroMemory(ZeroSsid, 32);
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)
536 // Passive scan Mode
537 DBGPRINT(RT_DEBUG_TRACE, ("Passive Scan Mode!\n"));
539 // Control state machine is not idle, reject the request
540 if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
541 return;
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;
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));
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)
559 // Use MLME enqueue method
560 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
561 if (NStatus != NDIS_STATUS_SUCCESS)
562 return;
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;
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);
578 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
580 else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_ACTIVE)
582 // Active scan Mode
583 DBGPRINT(RT_DEBUG_TRACE, ("Active Scan Mode!\n"));
585 // Control state machine is not idle, reject the request
586 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
587 return;
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;
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));
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)
605 // Use MLME enqueue method
606 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
607 if (NStatus != NDIS_STATUS_SUCCESS)
608 return;
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;
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);
624 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
626 else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_BEACON_TABLE)
628 // Beacon report Mode, report all the APS in current bss table
629 DBGPRINT(RT_DEBUG_TRACE, ("Beacon Report Mode!\n"));
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));
634 // Create beacon report from Bss table
635 AironetCreateBeaconReportFromBssTable(pAd);
637 // Set state to scanning
638 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
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);
644 else
646 // Wrong scan Mode
647 DBGPRINT(RT_DEBUG_TRACE, ("Wrong Scan Mode!\n"));
650 DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction <-----\n"));
654 ========================================================================
656 Routine Description:
658 Arguments:
660 Return Value:
661 None
663 Note:
665 ========================================================================
667 VOID AironetReportAction(
668 IN PRTMP_ADAPTER pAd,
669 IN MLME_QUEUE_ELEM *Elem)
671 PRM_REQUEST_ACTION pReq;
672 ULONG Now32;
674 NdisGetSystemUpTime(&Now32);
675 pAd->StaCfg.LastBeaconRxTime = Now32;
677 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
679 DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction ----->\n"));
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
695 // 2. Point to the correct index of action element, start from 0
696 pAd->StaCfg.CurrentRMReqIdx++;
698 // 3. Check for parallel actions
699 if (pAd->StaCfg.ParallelReq == TRUE)
701 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
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);
711 pAd->StaCfg.ParallelReq = FALSE;
712 pAd->StaCfg.CurrentRMReqIdx++;
715 if (pAd->StaCfg.CurrentRMReqIdx >= pAd->StaCfg.RMReqCnt)
717 // 4. There is no more unprocessed measurement request, go for transmit this report
718 AironetFinalReportAction(pAd);
719 pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
721 else
723 pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
725 if (pReq->Measurement.Channel != pAd->CommonCfg.Channel)
727 RTMPusecDelay(100000);
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);
735 DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction <-----\n"));
739 ========================================================================
741 Routine Description:
743 Arguments:
745 Return Value:
746 None
748 Note:
750 ========================================================================
752 VOID AironetFinalReportAction(
753 IN PRTMP_ADAPTER pAd)
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;
764 DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction ----->\n"));
766 // 0. Set up the frame pointer, Frame was inited at the end of message action
767 pDest = &pAd->StaCfg.FrameReportBuf[LENGTH_802_11];
769 // 1. Update report IAPP fields
770 pIAPP = (PAIRONET_IAPP_HEADER) pDest;
772 // 2. Copy Cisco SNAP header
773 NdisMoveMemory(pIAPP->CiscoSnapHeader, SNAP_AIRONET, LENGTH_802_1_H);
775 // 3. network order for this 16bit length
776 pIAPP->Length = cpu2be16(pAd->StaCfg.FrameReportLen - LENGTH_802_11 - LENGTH_802_1_H);
778 // 3.1 sanity check the report length, ignore it if there is nothing to report
779 if (be2cpu16(pIAPP->Length) <= 18)
780 return;
782 // 4. Type must be 0x32
783 pIAPP->Type = AIRONET_IAPP_TYPE;
785 // 5. SubType for report must be 0x81
786 pIAPP->SubType = AIRONET_IAPP_SUBTYPE_REPORT;
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);
792 // 7. SA is the client reporting which must be our MAC
793 COPY_MAC_ADDR(pIAPP->SA, pAd->CurrentAddress);
795 // 8. Copy the saved dialog token
796 pIAPP->Token = pAd->StaCfg.IAPPToken;
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);
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;
809 // Use MLME enqueue method
810 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
811 if (NStatus != NDIS_STATUS_SUCCESS)
812 return;
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);
819 // 11. Send using priority queue
820 MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
821 MlmeFreeMemory(pAd, pOutBuffer);
823 pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED;
825 DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction <-----\n"));
829 ========================================================================
831 Routine Description:
833 Arguments:
835 Return Value:
836 None
838 Note:
840 ========================================================================
842 VOID ChannelLoadReportAction(
843 IN PRTMP_ADAPTER pAd,
844 IN UCHAR Index)
846 PMEASUREMENT_REPORT_ELEMENT pReport;
847 PCHANNEL_LOAD_REPORT pLoad;
848 PUCHAR pDest;
849 UCHAR CCABusyFraction;
851 DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction ----->\n"));
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.
856 // 0. Setup pointer for processing beacon & probe response
857 pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
858 pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
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;
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;
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;
884 pLoad->CCABusy = CCABusyFraction;
885 DBGPRINT(RT_DEBUG_TRACE, ("CLBusyByte %ld, Duration %d, Result, %d\n", pAd->StaCfg.CLBusyBytes, pLoad->Duration, CCABusyFraction));
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));
891 // 4. Clear channel load measurement flag
892 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
894 // 5. reset to idle state
895 pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
897 DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction <-----\n"));
901 ========================================================================
903 Routine Description:
905 Arguments:
907 Return Value:
908 None
910 Note:
912 ========================================================================
914 VOID NoiseHistReportAction(
915 IN PRTMP_ADAPTER pAd,
916 IN UCHAR Index)
918 PMEASUREMENT_REPORT_ELEMENT pReport;
919 PNOISE_HIST_REPORT pNoise;
920 PUCHAR pDest;
921 UCHAR i,NoiseCnt;
922 USHORT TotalRPICnt, TotalRPISum;
924 DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction ----->\n"));
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;
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;
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;
954 for (i = 0; i < 8; i++)
956 TotalRPISum += pAd->StaCfg.RPIDensity[i];
957 DBGPRINT(RT_DEBUG_TRACE, ("RPI %d Conuts %d\n", i, pAd->StaCfg.RPIDensity[i]));
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;
965 DBGPRINT(RT_DEBUG_TRACE, ("Total RPI Conuts %d\n", TotalRPICnt));
967 // 5. Initialize noise count for the total summation of 0xff
968 NoiseCnt = 0;
969 for (i = 1; i < 8; i++)
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]));
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]));
982 pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(NOISE_HIST_REPORT));
984 // 7. Clear channel load measurement flag
985 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
987 // 8. reset to idle state
988 pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
990 DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction <-----\n"));
994 ========================================================================
996 Routine Description:
997 Prepare Beacon report action,
999 Arguments:
1000 pAd Pointer to our adapter
1002 Return Value:
1003 None
1005 Note:
1007 ========================================================================
1009 VOID BeaconReportAction(
1010 IN PRTMP_ADAPTER pAd,
1011 IN UCHAR Index)
1013 DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction ----->\n"));
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
1019 // reset Beacon index for next beacon request
1020 pAd->StaCfg.LastBssIndex = 0xff;
1022 // reset to idle state
1023 pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
1025 DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction <-----\n"));
1029 ========================================================================
1031 Routine Description:
1033 Arguments:
1034 Index Current BSSID in CCXBsstab entry index
1036 Return Value:
1038 Note:
1040 ========================================================================
1042 VOID AironetAddBeaconReport(
1043 IN PRTMP_ADAPTER pAd,
1044 IN ULONG Index,
1045 IN PMLME_QUEUE_ELEM pElem)
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;
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;
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))
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;
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;
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]));
1088 // Update other information here
1090 // Done
1091 return;
1094 // 2. Update reported Index
1095 pAd->StaCfg.LastBssIndex = Index;
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];
1101 // 4. Save the start offset of each Bss in report frame
1102 pAd->StaCfg.BssReportOffset[Index] = pAd->StaCfg.FrameReportLen;
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);
1114 // 6. Start thebeacon report format
1115 pBeaconReport = (PBEACON_REPORT) pDest;
1116 pDest += sizeof(BEACON_REPORT);
1117 Length += sizeof(BEACON_REPORT);
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;
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));
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);
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;
1143 // 10. Point to start of element ID
1144 pSrc += 2;
1145 pEid = (PEID_STRUCT) pSrc;
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))
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)
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;
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))
1175 // Matched, this is what we want
1176 NdisMoveMemory(pDest, pEid, pEid->Len + 2);
1177 pDest += (pEid->Len + 2);
1178 Length += (pEid->Len + 2);
1180 break;
1182 case IE_TIM:
1183 if (pEid->Len > 4)
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;
1190 else
1192 NdisMoveMemory(pDest, pEid, pEid->Len + 2);
1193 pDest += (pEid->Len + 2);
1194 Length += (pEid->Len + 2);
1196 break;
1198 default:
1199 break;
1201 // 12. Move to next element ID
1202 pSrc += (2 + pEid->Len);
1203 pEid = (PEID_STRUCT) pSrc;
1206 // 13. Update the length in the header, not include EID and length
1207 pReport->Length = Length - 4;
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));
1215 ========================================================================
1217 Routine Description:
1219 Arguments:
1220 Index Current BSSID in CCXBsstab entry index
1222 Return Value:
1224 Note:
1226 ========================================================================
1228 VOID AironetCreateBeaconReportFromBssTable(
1229 IN PRTMP_ADAPTER pAd)
1231 PMEASUREMENT_REPORT_ELEMENT pReport;
1232 PBEACON_REPORT pBeaconReport;
1233 UCHAR Index, ReqIdx;
1234 USHORT Length;
1235 PUCHAR pDest;
1236 PBSS_ENTRY pBss;
1238 // 0. setup base pointer
1239 ReqIdx = pAd->StaCfg.CurrentRMReqIdx;
1241 for (Index = 0; Index < pAd->StaCfg.CCXBssTab.BssNr; Index++)
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;
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);
1259 // 3. Start the beacon report format
1260 pBeaconReport = (PBEACON_REPORT) pDest;
1261 pDest += sizeof(BEACON_REPORT);
1262 Length += sizeof(BEACON_REPORT);
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);
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);
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);
1290 // 7. DS Parameter
1291 *pDest++ = 0x03;
1292 *pDest++ = 1;
1293 *pDest++ = pBss->Channel;
1294 Length += 3;
1296 // 8. IBSS parameter if presents
1297 if (pBss->BssType == BSS_ADHOC)
1299 *pDest++ = 0x06;
1300 *pDest++ = 2;
1301 *(PUSHORT) pDest = pBss->AtimWin;
1302 pDest += 2;
1303 Length += 4;
1306 // 9. Update length field, not include EID and length
1307 pReport->Length = Length - 4;
1309 // 10. Update total frame size
1310 pAd->StaCfg.FrameReportLen += Length;