2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 Paul Lin 04-06-15 Initial
37 #include "../rt_config.h"
40 ==========================================================================
42 association state machine init, including state transition and timer init
44 S - pointer to the association state machine
45 ==========================================================================
47 VOID AironetStateMachineInit(
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 ==========================================================================
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
69 ==========================================================================
71 VOID AironetMsgAction(
73 IN MLME_QUEUE_ELEM *Elem)
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)
94 // 2.1 Radio measurement must be on
95 if (pAd->StaCfg.CCXControl.field.RMEnable != 1)
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"));
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"));
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"));
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"));
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;
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.
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)
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)
206 // Save requests and execute actions later
207 NdisMoveMemory(&pAd->StaCfg.MeasurementRequest[Index], pReqElem, sizeof(RM_REQUEST_ACTION));
211 case MSRN_TYPE_FRAME_REQ:
212 // Since it's option, we will support later
213 // FrameRequestAction(pAd, pData);
220 // Point to next Measurement request
221 pData += sizeof(RM_REQUEST_ACTION);
222 Length -= sizeof(RM_REQUEST_ACTION);
225 // We accept request only, all others are dropped
226 case IE_MEASUREMENT_REPORT:
228 case IE_MEASUREMENT_CAPABILITY:
234 // 11. Update some flags and index
235 pAd->StaCfg.RMReqCnt = 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 ========================================================================
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);
280 // Unknown. Do nothing and return, this should never happen
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 ========================================================================
307 Prepare channel load report action, special scan operation added
311 pAd Pointer to our adapter
312 pData Start from element ID
319 ========================================================================
321 VOID ChannelLoadRequestAction(
322 IN PRTMP_ADAPTER pAd,
325 PRM_REQUEST_ACTION pReq;
326 MLME_SCAN_REQ_STRUCT ScanReq;
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.
345 // Control state machine is not idle, reject the request
346 if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
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)
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"));
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 ========================================================================
401 Prepare noise histogram report action, special scan operation added
405 pAd Pointer to our adapter
406 pData Start from element ID
413 ========================================================================
415 VOID NoiseHistRequestAction(
416 IN PRTMP_ADAPTER pAd,
419 PRM_REQUEST_ACTION pReq;
420 MLME_SCAN_REQ_STRUCT ScanReq;
421 UCHAR ZeroSsid[32], i;
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.
439 // Control state machine is not idle, reject the request
440 if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
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)
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"));
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 ========================================================================
498 Prepare Beacon report action, special scan operation added
502 pAd Pointer to our adapter
503 pData Start from element ID
510 ========================================================================
512 VOID BeaconRequestAction(
513 IN PRTMP_ADAPTER pAd,
516 PRM_REQUEST_ACTION pReq;
518 PUCHAR pOutBuffer = NULL;
519 PHEADER_802_11 pNullFrame;
520 MLME_SCAN_REQ_STRUCT ScanReq;
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)
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))
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)
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"));
578 pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
580 else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_ACTIVE)
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)
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)
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"));
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);
647 DBGPRINT(RT_DEBUG_TRACE, ("Wrong Scan Mode!\n"));
650 DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction <-----\n"));
654 ========================================================================
665 ========================================================================
667 VOID AironetReportAction(
668 IN PRTMP_ADAPTER pAd,
669 IN MLME_QUEUE_ELEM *Elem)
671 PRM_REQUEST_ACTION pReq;
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);
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;
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 ========================================================================
750 ========================================================================
752 VOID AironetFinalReportAction(
753 IN PRTMP_ADAPTER pAd)
756 PAIRONET_IAPP_HEADER pIAPP;
757 PHEADER_802_11 pHeader;
758 UCHAR AckRate = RATE_2;
759 USHORT AckDuration = 0;
761 PUCHAR pOutBuffer = NULL;
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)
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;
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)
814 // 10. Prepare report frame with dynamic outbuffer. Just simply copy everything.
815 MakeOutgoingFrame(pOutBuffer, &FrameLen,
816 pAd->StaCfg.FrameReportLen, pAd->StaCfg.FrameReportBuf,
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 ========================================================================
840 ========================================================================
842 VOID ChannelLoadReportAction(
843 IN PRTMP_ADAPTER pAd,
846 PMEASUREMENT_REPORT_ELEMENT pReport;
847 PCHANNEL_LOAD_REPORT pLoad;
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
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;
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 ========================================================================
912 ========================================================================
914 VOID NoiseHistReportAction(
915 IN PRTMP_ADAPTER pAd,
918 PMEASUREMENT_REPORT_ELEMENT pReport;
919 PNOISE_HIST_REPORT pNoise;
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;
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;
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
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 ========================================================================
997 Prepare Beacon report action,
1000 pAd Pointer to our adapter
1007 ========================================================================
1009 VOID BeaconReportAction(
1010 IN PRTMP_ADAPTER pAd,
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:
1034 Index Current BSSID in CCXBsstab entry index
1040 ========================================================================
1042 VOID AironetAddBeaconReport(
1043 IN PRTMP_ADAPTER pAd,
1045 IN PMLME_QUEUE_ELEM pElem)
1052 PFRAME_802_11 pFrame;
1053 PMEASUREMENT_REPORT_ELEMENT pReport;
1055 PBEACON_REPORT pBeaconReport;
1058 // 0. Setup pointer for processing beacon & probe response
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
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
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
1161 NdisMoveMemory(pDest, pEid, pEid->Len + 2);
1162 pDest += (pEid->Len + 2);
1163 Length += (pEid->Len + 2);
1166 case IE_MEASUREMENT_CAPABILITY:
1167 // Since this IE is duplicated with WPA security IE, we has to do sanity check before
1169 // 1. It also has fixed 6 bytes IE length.
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);
1185 // May truncate and report the first 4 bytes only, with the eid & len, total should be 6
1186 NdisMoveMemory(pDest, pEid, 6);
1192 NdisMoveMemory(pDest, pEid, pEid->Len + 2);
1193 pDest += (pEid->Len + 2);
1194 Length += (pEid->Len + 2);
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:
1220 Index Current BSSID in CCXBsstab entry index
1226 ========================================================================
1228 VOID AironetCreateBeaconReportFromBssTable(
1229 IN PRTMP_ADAPTER pAd)
1231 PMEASUREMENT_REPORT_ELEMENT pReport;
1232 PBEACON_REPORT pBeaconReport;
1233 UCHAR Index, ReqIdx;
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];
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);
1278 *pDest++ = pBss->SsidLen;
1279 NdisMoveMemory(pDest, pBss->Ssid, pBss->SsidLen);
1280 pDest += pBss->SsidLen;
1281 Length += (2 + pBss->SsidLen);
1283 // 6. Create SupportRates
1285 *pDest++ = pBss->SupRateLen;
1286 NdisMoveMemory(pDest, pBss->SupRate, pBss->SupRateLen);
1287 pDest += pBss->SupRateLen;
1288 Length += (2 + pBss->SupRateLen);
1293 *pDest++ = pBss->Channel;
1296 // 8. IBSS parameter if presents
1297 if (pBss->BssType == BSS_ADHOC)
1301 *(PUSHORT) pDest = pBss->AtimWin;
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;