mlme.c
来自「RT73无线网络芯片最新linux下驱动 支持到linux2.6.24 并向下兼」· C语言 代码 · 共 1,835 行 · 第 1/5 页
C
1,835 行
VOID LinkDownExec( IN PVOID SystemSpecific1, IN PVOID FunctionContext, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3){ //RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;}VOID MlmeAutoScan( IN PRTMP_ADAPTER pAd){ // check CntlMachine.CurrState to avoid collision with NDIS SetOID request if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { DBGPRINT(RT_DEBUG_TRACE, "MMCHK - Driver auto scan\n"); MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_BSSID_LIST_SCAN, 0, NULL); RTUSBMlmeUp(pAd); }} VOID MlmeAutoRecoverNetwork( IN PRTMP_ADAPTER pAd){ // check CntlMachine.CurrState to avoid collision with NDIS SetOID request if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { NDIS_802_11_SSID OidSsid; OidSsid.SsidLength = pAd->PortCfg.SsidLen; NdisMoveMemory(OidSsid.Ssid, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen); DBGPRINT(RT_DEBUG_TRACE, "MMCHK - Driver auto recovering network - %s\n", pAd->PortCfg.Ssid); MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID, sizeof(NDIS_802_11_SSID), &OidSsid); RTUSBMlmeUp(pAd); }}//2007/11/09:KH replace the original MlmeAutoReconnectLastSSIDVOID MlmeAutoReconnectLastSSID( IN PRTMP_ADAPTER pAd){ // check CntlMachine.CurrState to avoid collision with NDIS SetOID request MLME_SCAN_REQ_STRUCT ScanReq; ULONG Now= pAd->Mlme.Now32; if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && ((pAd->PortCfg.LastScanTime + (10*HZ)) >= Now)) // BUG (10 sec) { if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) { NDIS_802_11_SSID OidSsid; OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen; NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); DBGPRINT(RT_DEBUG_TRACE, "Driver auto reconnect to last OID_802_11_SSID setting - %s\n", pAd->MlmeAux.AutoReconnectSsid); /* carella modify: if no SSID, sta should not try to connect AP in scan table */ if(OidSsid.SsidLength) { MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID, sizeof(NDIS_802_11_SSID), &OidSsid); RTUSBMlmeUp(pAd); } } } else if ((pAd->PortCfg.LastScanTime + (10*HZ)) < Now) { // check CntlMachine.CurrState to avoid collision with NDIS SetOID request DBGPRINT(RT_DEBUG_TRACE, "MMCHK - FastRoaming, No eligable entry, try new scan!\n"); pAd->PortCfg.ScanCnt = 2; pAd->PortCfg.LastScanTime = Now; ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE); MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); RTUSBMlmeUp(pAd); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; }}/* ========================================================================== Validate SSID for connection try and rescan purpose Valid SSID will have visible chars only. The valid length is from 0 to 32. ========================================================================== */BOOLEAN MlmeValidateSSID( IN PUCHAR pSsid, IN UCHAR SsidLen){ int index; if (SsidLen > MAX_LEN_OF_SSID) return (FALSE); // Check each character value for (index = 0; index < SsidLen; index++) { if (pSsid[index] < 0x20) return (FALSE); } // All checked return (TRUE);}/* ========================================================================== Description: This routine checks if there're other APs out there capable for roaming. Caller should call this routine only when Link up in INFRA mode and channel quality is below CQI_GOOD_THRESHOLD. Output: ========================================================================== */VOID MlmeCheckForRoaming( IN PRTMP_ADAPTER pAd, IN ULONG Now32){ USHORT i; BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; BSS_ENTRY *pBss; DBGPRINT(RT_DEBUG_TRACE, "==> MlmeCheckForRoaming::pAd->ScanTab.BssNr = %d\n", pAd->ScanTab.BssNr); // put all roaming candidates into RoamTab, and sort in RSSI order BssTableInit(pRoamTab); for (i = 0; i < pAd->ScanTab.BssNr; i++) { pBss = &pAd->ScanTab.BssEntry[i]; DBGPRINT(RT_DEBUG_TRACE, "MlmeCheckForRoaming::pBss->LastBeaconRxTime = %d\n", pBss->LastBeaconRxTime); if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32) { DBGPRINT(RT_DEBUG_TRACE, "1: AP disappear::Now32 = %d\n", Now32); continue; // AP disappear } if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING) { DBGPRINT(RT_DEBUG_TRACE, "2: RSSI too weak::Rssi[%d] - RSSI_THRESHOLD_FOR_ROAMING[%d]\n", pBss->Rssi, RSSI_THRESHOLD_FOR_ROAMING); continue; // RSSI too weak. forget it. } if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->PortCfg.Bssid)) { DBGPRINT(RT_DEBUG_TRACE, "3: skip current AP\n"); continue; // skip current AP } if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen)) { DBGPRINT(RT_DEBUG_TRACE, "4: skip different SSID\n"); continue; // skip different SSID } if (pBss->Rssi < (pAd->PortCfg.LastRssi + RSSI_DELTA)) { DBGPRINT(RT_DEBUG_TRACE, "5: only AP with stronger RSSI is eligible for roaming\n"); continue; // only AP with stronger RSSI is eligible for roaming } // AP passing all above rules is put into roaming candidate table NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); pRoamTab->BssNr += 1; } if (pRoamTab->BssNr > 0) { // check CntlMachine.CurrState to avoid collision with NDIS SetOID request if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { pAd->RalinkCounters.PoorCQIRoamingCount ++; DBGPRINT(RT_DEBUG_TRACE, "MMCHK - Roaming attempt #%d\n", pAd->RalinkCounters.PoorCQIRoamingCount); MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); RTUSBMlmeUp(pAd); } } DBGPRINT(RT_DEBUG_TRACE, "<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr); }/* ========================================================================== Description: This routine checks if there're other APs out there capable for roaming. Caller should call this routine only when link up in INFRA mode and channel quality is below CQI_GOOD_THRESHOLD. Output: ========================================================================== */VOID MlmeCheckForFastRoaming( IN PRTMP_ADAPTER pAd, IN ULONG Now){ USHORT i; BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; BSS_ENTRY *pBss; MLME_SCAN_REQ_STRUCT ScanReq; DBGPRINT(RT_DEBUG_TRACE, "==> MlmeCheckForFastRoaming\n"); // // If Scan talbe is fresh within 10 sec, then we can select the AP with the best RSSI // Otherwise refresh this scan table. // //KH modified time-unit from jiffies to HZ if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && ((pAd->PortCfg.LastScanTime + 10 * HZ) >= Now)) { BssTableInit(pRoamTab); // put all roaming candidates into RoamTab, and sort in RSSI order for (i = 0; i < pAd->ScanTab.BssNr; i++) { pBss = &pAd->ScanTab.BssEntry[i]; /*2007/11/05:KH replace the line"if ((pBss->Rssi <= 45) && (pBss->Channel == pAd->PortCfg.Channel))" to enable the roaming between different channels. */ if(pBss->Rssi<=45) continue; // RSSI too weak. forget it. if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->PortCfg.Bssid)) continue; // skip current AP //2007/12/20:correct hidden bugs if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen) &&pBss->SsidLen>0&&pBss->Ssid[0]!=0 ) continue; // skip different SSID if (pBss->Rssi < (pAd->PortCfg.LastRssi + RSSI_DELTA)) continue; // skip AP without better RSSI DBGPRINT(RT_DEBUG_TRACE, "LastRssi = %d, pBss->Rssi = %d\n", pAd->PortCfg.LastRssi, pBss->Rssi); // AP passing all above rules is put into roaming candidate table NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); //2007/12/06:KH add to fix roaming with hidden SSID if(pBss->SsidLen==0||pBss->Ssid[0]==0) { DBGPRINT(RT_DEBUG_TRACE, "Roaming With NULL SSID and BSSID[#%d]=%s", pRoamTab->BssNr,pBss->Bssid); pRoamTab->BssEntry[pRoamTab->BssNr].SsidLen=pAd->PortCfg.SsidLen; NdisMoveMemory(pRoamTab->BssEntry[pRoamTab->BssNr].Ssid, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen); DBGPRINT(RT_DEBUG_TRACE, "Roaming With NULL SSID after modified the BSSID[#%d]=%s with SSID[%d]=%s", pRoamTab->BssNr,pBss->Bssid,pRoamTab->BssEntry[pRoamTab->BssNr].SsidLen,pRoamTab->BssEntry[pRoamTab->BssNr].Ssid); } pRoamTab->BssNr += 1; } if (pRoamTab->BssNr > 0) { pAd->RalinkCounters.PoorCQIRoamingCount ++; DBGPRINT(RT_DEBUG_TRACE, "MMCHK - Roaming attempt #%d\n", pAd->RalinkCounters.PoorCQIRoamingCount); MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); RTUSBMlmeUp(pAd); } } // Maybe site survey required else { if ((pAd->PortCfg.LastScanTime + 10*HZ) < Now) { // check CntlMachine.CurrState to avoid collision with NDIS SetOID request DBGPRINT(RT_DEBUG_TRACE, "MMCHK - Roaming, No eligable entry, try a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid); pAd->PortCfg.ScanCnt = 2; pAd->PortCfg.LastScanTime = Now; ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE); MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); RTUSBMlmeUp(pAd); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; } } DBGPRINT(RT_DEBUG_TRACE, "<== MlmeCheckForFastRoaming\n"); }/* ========================================================================== Description: This routine calculates TxPER, RxPER of the past N-sec period. And according to the calculation result, ChannelQuality is calculated here to decide if current AP is still doing the job. If ChannelQuality is not good, a ROAMing attempt may be tried later. Output: PortCfg.ChannelQuality - 0..100 NOTE: This routine decide channle quality based on RX CRC error ratio. Caller should make sure a function call to NICUpdateRawCounters(pAd) is performed right before this routine, so that this routine can decide channel quality based on the most up-to-date information ========================================================================== */VOID MlmeCalculateChannelQuality( IN PRTMP_ADAPTER pAd, IN ULONG Now32){ ULONG TxOkCnt, TxCnt, TxPER, TxPRR; ULONG RxCnt, RxPER; UCHAR NorRssi; // // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics // TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount; TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount; if (TxCnt < 5) { TxPER = 0; TxPRR = 0; } else { TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt; TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt; } // // calculate RX PER - don't take RxPER into consideration if too few sample // RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt; if (RxCnt < 5) RxPER = 0; else RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt; // // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER // if (INFRA_ON(pAd) && (TxOkCnt < 2) && // no heavy traffic (pAd->PortCfg.LastBeaconRxTime + BEACON_LOST_TIME < Now32)) { DBGPRINT(RT_DEBUG_TRACE, "BEACON lost > %d msec with TxOkCnt=%d -> CQI=0\n", BEACON_LOST_TIME, TxOkCnt); pAd->Mlme.ChannelQuality = 0; } else { // Normalize Rssi if (pAd->PortCfg.LastRssi > 0x50) NorRssi = 100; else if (pAd->PortCfg.LastRssi < 0x20) NorRssi = 0; else NorRssi = (pAd->PortCfg.LastRssi - 0x20) * 2; // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi + TX_WEIGHTING * (100 - TxPRR) + RX_WEIGHTING* (100 - RxPER)) / 100; if (pAd->Mlme.ChannelQuality >= 100) pAd->Mlme.ChannelQuality = 100; } DBGPRINT(RT_DEBUG_INFO, "MMCHK - CQI= %d (Tx Fail=%d/Retry=%d/Total=%d, Rx Fail=%d/Total=%d, RSSI=%d dbm)\n", pAd->Mlme.ChannelQuality, pAd->RalinkCounters.OneSecTxFailCount,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?