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;