📄 aironet.c
字号:
return; // Fill out stuff for scan request ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_NOISE); MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; // Reset some internal control flags to make sure this scan works. BssTableInit(&pAd->StaCfg.CCXBssTab); pAd->StaCfg.ScanCnt = 0; pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; pAd->StaCfg.CCXReqType = MSRN_TYPE_NOISE_HIST_REQ; DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel)); // If it's non serving channel scan, send out a null frame with PSM bit on. if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) { // Use MLME enqueue method NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) return; pNullFrame = (PHEADER_802_11) pOutBuffer; // Make the power save Null frame with PSM bit on MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); pNullFrame->Duration = 0; pNullFrame->FC.Type = BTYPE_DATA; pNullFrame->FC.PwrMgmt = PWR_SAVE; // Send using priority queue MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); RTMPusecDelay(5000); } // Reset the statistics for (i = 0; i < 8; i++) pAd->StaCfg.RPIDensity[i] = 0; // Enable Rx with promiscuous reception RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010); // Set channel load measurement flag RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT); pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction <-----\n"));}/* ======================================================================== Routine Description: Prepare Beacon report action, special scan operation added to support Arguments: pAd Pointer to our adapter pData Start from element ID Return Value: None Note: ========================================================================*/VOID BeaconRequestAction( IN PRTMP_ADAPTER pAd, IN UCHAR Index) { PRM_REQUEST_ACTION pReq; NDIS_STATUS NStatus; PUCHAR pOutBuffer = NULL; PHEADER_802_11 pNullFrame; MLME_SCAN_REQ_STRUCT ScanReq; UCHAR ZeroSsid[32]; DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction ----->\n")); pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index]; NdisZeroMemory(ZeroSsid, 32); // Prepare for special scan request // The scan definition is different with our Active, Passive scan definition. // For CCX2, Active means send out probe request with broadcast BSSID. // Passive means no probe request sent, only listen to the beacons. // The channel scanned is fixed as specified, no need to scan all channels. // The scan wait time is specified in the request too. if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_PASSIVE) { // Passive scan Mode DBGPRINT(RT_DEBUG_TRACE, ("Passive Scan Mode!\n")); // Control state machine is not idle, reject the request if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0)) return; // Fill out stuff for scan request ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_PASSIVE); MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; // Reset some internal control flags to make sure this scan works. BssTableInit(&pAd->StaCfg.CCXBssTab); pAd->StaCfg.ScanCnt = 0; pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ; DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration)); // If it's non serving channel scan, send out a null frame with PSM bit on. if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) { // Use MLME enqueue method NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) return; pNullFrame = (PHEADER_802_11) pOutBuffer; // Make the power save Null frame with PSM bit on MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); pNullFrame->Duration = 0; pNullFrame->FC.Type = BTYPE_DATA; pNullFrame->FC.PwrMgmt = PWR_SAVE; // Send using priority queue MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); RTMPusecDelay(5000); } pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; } else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_ACTIVE) { // Active scan Mode DBGPRINT(RT_DEBUG_TRACE, ("Active Scan Mode!\n")); // Control state machine is not idle, reject the request if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) return; // Fill out stuff for scan request ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_ACTIVE); MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; // Reset some internal control flags to make sure this scan works. BssTableInit(&pAd->StaCfg.CCXBssTab); pAd->StaCfg.ScanCnt = 0; pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel; pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration; pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ; DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration)); // If it's non serving channel scan, send out a null frame with PSM bit on. if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel) { // Use MLME enqueue method NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) return; pNullFrame = (PHEADER_802_11) pOutBuffer; // Make the power save Null frame with PSM bit on MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid); pNullFrame->Duration = 0; pNullFrame->FC.Type = BTYPE_DATA; pNullFrame->FC.PwrMgmt = PWR_SAVE; // Send using priority queue MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11)); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n")); RTMPusecDelay(5000); } pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; } else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_BEACON_TABLE) { // Beacon report Mode, report all the APS in current bss table DBGPRINT(RT_DEBUG_TRACE, ("Beacon Report Mode!\n")); // Copy current BSS table to CCX table, we can omit this step later on. NdisMoveMemory(&pAd->StaCfg.CCXBssTab, &pAd->ScanTab, sizeof(BSS_TABLE)); // Create beacon report from Bss table AironetCreateBeaconReportFromBssTable(pAd); // Set state to scanning pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING; // Enqueue report request // Cisco scan request is finished, prepare beacon report MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL); } else { // Wrong scan Mode DBGPRINT(RT_DEBUG_TRACE, ("Wrong Scan Mode!\n")); } DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction <-----\n"));}/* ======================================================================== Routine Description: Arguments: Return Value: None Note: ========================================================================*/VOID AironetReportAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem){ PRM_REQUEST_ACTION pReq; ULONG Now32; NdisGetSystemUpTime(&Now32); pAd->StaCfg.LastBeaconRxTime = Now32; pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction ----->\n")); // 1. Parse measurement type and call appropriate functions if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) // Channel Load measurement request ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) // Noise Histogram measurement request NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ) // Beacon measurement request BeaconReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); else // Unknown. Do nothing and return ; // 2. Point to the correct index of action element, start from 0 pAd->StaCfg.CurrentRMReqIdx++; // 3. Check for parallel actions if (pAd->StaCfg.ParallelReq == TRUE) { pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; // Process next action right away if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ) // Channel Load measurement request ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ) // Noise Histogram measurement request NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx); pAd->StaCfg.ParallelReq = FALSE; pAd->StaCfg.CurrentRMReqIdx++; } if (pAd->StaCfg.CurrentRMReqIdx >= pAd->StaCfg.RMReqCnt) { // 4. There is no more unprocessed measurement request, go for transmit this report AironetFinalReportAction(pAd); pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE; } else { pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx]; if (pReq->Measurement.Channel != pAd->CommonCfg.Channel) { RTMPusecDelay(100000); } // 5. There are more requests to be measure MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL); MlmeHandler(pAd); } DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction <-----\n"));}/* ======================================================================== Routine Description: Arguments: Return Value: None Note: ========================================================================*/VOID AironetFinalReportAction( IN PRTMP_ADAPTER pAd){ PUCHAR pDest; PAIRONET_IAPP_HEADER pIAPP; PHEADER_802_11 pHeader; UCHAR AckRate = RATE_2; USHORT AckDuration = 0; NDIS_STATUS NStatus; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0; DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction ----->\n")); // 0. Set up the frame pointer, Frame was inited at the end of message action pDest = &pAd->StaCfg.FrameReportBuf[LENGTH_802_11]; // 1. Update report IAPP fields pIAPP = (PAIRONET_IAPP_HEADER) pDest; // 2. Copy Cisco SNAP header NdisMoveMemory(pIAPP->CiscoSnapHeader, SNAP_AIRONET, LENGTH_802_1_H); // 3. network order for this 16bit length pIAPP->Length = cpu2be16(pAd->StaCfg.FrameReportLen - LENGTH_802_11 - LENGTH_802_1_H); // 3.1 sanity check the report length, ignore it if there is nothing to report if (be2cpu16(pIAPP->Length) <= 18) return; // 4. Type must be 0x32 pIAPP->Type = AIRONET_IAPP_TYPE; // 5. SubType for report must be 0x81 pIAPP->SubType = AIRONET_IAPP_SUBTYPE_REPORT; // 6. DA is not used and must be zero, although the whole frame was cleared at the start of function // We will do it again here. We can use BSSID instead COPY_MAC_ADDR(pIAPP->DA, pAd->CommonCfg.Bssid); // 7. SA is the client reporting which must be our MAC COPY_MAC_ADDR(pIAPP->SA, pAd->CurrentAddress); // 8. Copy the saved dialog token pIAPP->Token = pAd->StaCfg.IAPPToken; // 9. Make the Report frame 802.11 header // Reuse function in wpa.c pHeader = (PHEADER_802_11) pAd->StaCfg.FrameReportBuf; pAd->Sequence ++; WpaMacHeaderInit(pAd, pHeader, 0, pAd->CommonCfg.Bssid); // ACK size is 14 include CRC, and its rate is based on real time information AckRate = pAd->CommonCfg.ExpectedACKRate[pAd->CommonCfg.MlmeRate]; AckDuration = RTMPCalcDuration(pAd, AckRate, 14); pHeader->Duration = pAd->CommonCfg.Dsifs + AckDuration; // Use MLME enqueue method NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory if (NStatus != NDIS_STATUS_SUCCESS) return; // 10. Prepare report frame with dynamic outbuffer. Just simply copy everything. MakeOutgoingFrame(pOutBuffer, &FrameLen, pAd->StaCfg.FrameReportLen, pAd->StaCfg.FrameReportBuf, END_OF_ARGS); // 11. Send using priority queue MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED; DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction <-----\n"));}/* ======================================================================== Routine Description: Arguments: Return Value: None Note: ========================================================================*/VOID ChannelLoadReportAction( IN PRTMP_ADAPTER pAd, IN UCHAR Index) { PMEASUREMENT_REPORT_ELEMENT pReport; PCHANNEL_LOAD_REPORT pLoad; PUCHAR pDest; UCHAR CCABusyFraction; DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction ----->\n")); // Disable Rx with promiscuous reception, make it back to normal RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification. // 0. Setup pointer for processing beacon & probe response pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen]; pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest; // 1. Fill Measurement report element field. pReport->Eid = IE_MEASUREMENT_REPORT; // Fixed Length at 9, not include Eid and length fields pReport->Length = 9; pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token; pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode; pReport->Type = MSRN_TYPE_CHANNEL_LOAD_REQ; // 2. Fill channel report measurement data pDest += sizeof(MEASUREMENT_REPORT_ELEMENT); pLoad = (PCHANNEL_LOAD_REPORT) pDest; pLoad->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel; pLoad->Spare = 0; pLoad->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration; // 3. Calculate the CCA Busy Fraction // (Bytes + ACK size) * 8 / Tx speed * 255 / 1000 / measurement duration, use 24 us Tx speed // = (Bytes + ACK) / 12 / duration // 9 is the good value for pAd->StaCfg.CLFactor // CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 9 / pLoad->Duration); CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / pAd->StaCfg.CLFactor / pLoad->Duration);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -