⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mlme.c

📁 D-link 无线usb网卡的Linux无线网卡驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:

		DBGPRINT(RT_DEBUG_TRACE, "Driver auto reconnect to last OID_802_11_SSID setting - %s\n", pAd->MlmeAux.AutoReconnectSsid);

		// We will only try this attemp once, therefore change the AutoReconnect flag afterwards.
		pAd->MlmeAux.CurrReqIsFromNdis = FALSE;
					
		MlmeEnqueue(pAd, 
					MLME_CNTL_STATE_MACHINE, 
					OID_802_11_SSID, 
					sizeof(NDIS_802_11_SSID), 
					&OidSsid,
					FALSE);
		RTUSBMlmeUp(pAd);
	}
}

/*
	==========================================================================
	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, FALSE);
			RTUSBMlmeUp(pAd);
		}
	}
	DBGPRINT(RT_DEBUG_TRACE, "<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr);	 
}

/*
	==========================================================================
	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, 
		pAd->RalinkCounters.OneSecTxRetryOkCount, 
		TxCnt, 
		pAd->RalinkCounters.OneSecRxFcsErrCnt, 
		RxCnt, pAd->PortCfg.LastRssi - pAd->BbpRssiToDbmDelta);

}

/*
	==========================================================================
	Description:
		This routine calculates the acumulated TxPER of eaxh TxRate. And 
		according to the calculation result, change PortCfg.TxRate which 
		is the stable TX Rate we expect the Radio situation could sustained. 

		PortCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} 
	Output:
		PortCfg.TxRate - 
		

	NOTE:
		call this routine every second
	==========================================================================
 */
VOID MlmeDynamicTxRateSwitching(
	IN PRTMP_ADAPTER pAd)
{
	UCHAR	UpRate, DownRate, CurrRate;
	ULONG	TxTotalCnt, NewBasicRateBitmap;
	ULONG	TxErrorRatio = 0;
	BOOLEAN fUpgradeQuality = FALSE;
	SHORT	dbm = pAd->PortCfg.AvgRssi - pAd->BbpRssiToDbmDelta;

	CurrRate = pAd->PortCfg.TxRate;

	// do not reply ACK using TX rate higher than normal DATA TX rate
	NewBasicRateBitmap = pAd->PortCfg.BasicRateBitmap & BasicRateMask[CurrRate];
	RTUSBWriteMACRegister(pAd, TXRX_CSR5, NewBasicRateBitmap);
	
	// if no traffic in the past 1-sec period, don't change TX rate,
	// but clear all bad history. because the bad history may affect the next 
	// Chariot throughput test
	TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + 
				 pAd->RalinkCounters.OneSecTxRetryOkCount + 
				 pAd->RalinkCounters.OneSecTxFailCount;

	if (TxTotalCnt)
		TxErrorRatio = ((pAd->RalinkCounters.OneSecTxRetryOkCount + pAd->RalinkCounters.OneSecTxFailCount) *100) / TxTotalCnt;
	
	DBGPRINT_RAW(RT_DEBUG_TRACE,"%d: NDIS push BE=%d, BK=%d, VI=%d, VO=%d, TX/RX AGGR=<%d,%d>, p-NDIS=%d, RSSI=%d, ACKbmap=%03x, PER=%d%%\n",
		RateIdToMbps[CurrRate],
		pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE],
		pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK],
		pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI],
		pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO],
		pAd->RalinkCounters.OneSecTxAggregationCount,
		pAd->RalinkCounters.OneSecRxAggregationCount,
		pAd->RalinkCounters.PendingNdisPacketCount, 
		dbm,
		NewBasicRateBitmap & 0xfff,
		TxErrorRatio);
	
	if (! OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
		return;
		
	//
	// CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
	//		   (criteria copied from RT2500 for Netopia case)
	//
	if (TxTotalCnt <= 15)
	{
		TxErrorRatio = 0;
		pAd->DrsCounters.TxRateUpPenalty = 0;
		NdisZeroMemory(pAd->DrsCounters.TxQuality, MAX_LEN_OF_SUPPORTED_RATES);
		NdisZeroMemory(pAd->DrsCounters.PER, MAX_LEN_OF_SUPPORTED_RATES);

		if (dbm >= -65)
			pAd->PortCfg.TxRate = RATE_54;
		else if (dbm >= -66)
			pAd->PortCfg.TxRate = RATE_48;
		else if (dbm >= -70)
			pAd->PortCfg.TxRate = RATE_36;
		else if (dbm >= -74)
			pAd->PortCfg.TxRate = RATE_24;
		else if (dbm >= -77)
			pAd->PortCfg.TxRate = RATE_18;	
		else if (dbm >= -79)
			pAd->PortCfg.TxRate = RATE_12;
		else if (dbm >= -81)
		{
			// in 11A or 11G-only mode, no CCK rates available
			if ((pAd->PortCfg.Channel > 14) || (pAd->PortCfg.PhyMode == PHY_11G))
				pAd->PortCfg.TxRate = RATE_9;
			else			
				pAd->PortCfg.TxRate = RATE_11;
		}		
		else 
		{
			// in 11A or 11G-only mode, no CCK rates available
			if ((pAd->PortCfg.Channel > 14) || (pAd->PortCfg.PhyMode == PHY_11G))
				pAd->PortCfg.TxRate = RATE_6;
			else
			{
				if (dbm >= -82)
					pAd->PortCfg.TxRate = RATE_11;
				else if (dbm >= -84)
					pAd->PortCfg.TxRate = RATE_5_5;
				else if (dbm >= -85)
					pAd->PortCfg.TxRate = RATE_2; 
				else
					pAd->PortCfg.TxRate = RATE_1; 
			}
		}

		if (pAd->PortCfg.TxRate > pAd->PortCfg.MaxTxRate)
			pAd->PortCfg.TxRate = pAd->PortCfg.MaxTxRate;
			
		return;
	}

	//
	// CASE2. enough TX samples, tune TX rate based on TxPER
	//
	do
	{
		pAd->DrsCounters.CurrTxRateStableTime ++;

		// decide the next upgrade rate and downgrade rate, if any
		if ((pAd->PortCfg.Channel > 14) ||		// must be in 802.11A band
			(pAd->PortCfg.PhyMode == PHY_11G))	// G-only mode, no CCK rates available
		{
			UpRate = Phy11ANextRateUpward[CurrRate];
			DownRate = Phy11ANextRateDownward[CurrRate];
		}
		else
		{
			UpRate = Phy11BGNextRateUpward[CurrRate];
			DownRate = Phy11BGNextRateDownward[CurrRate];
		}

		if (UpRate > pAd->PortCfg.MaxTxRate)
			UpRate = pAd->PortCfg.MaxTxRate;

		TxErrorRatio = ((pAd->RalinkCounters.OneSecTxRetryOkCount + pAd->RalinkCounters.OneSecTxFailCount) *100) / TxTotalCnt;
		   
		// downgrade TX quality if PER >= Rate-Down threshold
		if (TxErrorRatio >= RateDownPER[CurrRate])
		{
			pAd->DrsCounters.TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
		}
		// upgrade TX quality if PER <= Rate-Up threshold
		else if (TxErrorRatio <= RateUpPER[CurrRate])
		{
			fUpgradeQuality = TRUE;
			if (pAd->DrsCounters.TxQuality[CurrRate])
				pAd->DrsCounters.TxQuality[CurrRate] --;  // quality very good in CurrRate
					
			if (pAd->DrsCounters.TxRateUpPenalty)
				pAd->DrsCounters.TxRateUpPenalty --;
			else if (pAd->DrsCounters.TxQuality[UpRate])
				pAd->DrsCounters.TxQuality[UpRate] --;	  // may improve next UP rate's quality
		}

		pAd->DrsCounters.PER[CurrRate] = (UCHAR)TxErrorRatio;

#if 1	   
		// 2004-3-13 special case: Claim noisy environment

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -