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

📄 soft_ap.c

📁 Ralink RT61 SoftAP Driver source code. RT61:MiniPCI
💻 C
📖 第 1 页 / 共 4 页
字号:
    			
    			if (bFindIt == TRUE)
    				break;
    		};
    	}
    	else
    	{
		    for (ch=0; ch<pAd->ChannelListNum; ch++)
		    {
		        AsicSwitchChannel(pAd, pAd->ChannelList[ch].Channel);
		        AsicLockChannel(pAd, pAd->ChannelList[ch].Channel);
		        pAd->Counters8023.GoodReceives = 0;
		        pAd->Counters8023.RxErrors = 0;
		        pAd->PortCfg.AutoChannel_MaxRssi = 0;
		        pAd->PortCfg.AutoChannel_Channel = pAd->ChannelList[ch].Channel;
		        max_rssi[ch]=0;
		        RTMPusecDelay(200000); // 0.2 sec at each channel
		        max_rssi[ch] = pAd->PortCfg.AutoChannel_MaxRssi;

		        RTMP_IO_READ32(pAd, STA_CSR1, &FalseCca);
		        FalseCca = FalseCca >> 16;
		        RTMP_IO_READ32(pAd, STA_CSR0, &FcsError);
		        FcsError &= 0x0000ffff;
		        
		        if (max_rssi[ch])
		        {
		            dirtyness[ch] += 10;
		        }
		        DBGPRINT(RT_DEBUG_TRACE,"Sleep at ch#%d to collect RX=%d, RSSI=%d, CRC error=%d, False CCA=%d\n", 
		            pAd->ChannelList[ch].Channel, pAd->Counters8023.GoodReceives, max_rssi[ch] - pAd->BbpRssiToDbmDelta, FcsError, FalseCca);
		    }
	    
		    pAd->PortCfg.AutoChannel_Channel = 0;

		    DBGPRINT(RT_DEBUG_TRACE,"Dirtyness = %d.%d.%d.%d - %d.%d.%d.%d - %d.%d.%d.%d - %d.%d\n", 
		        dirtyness[0], dirtyness[1], dirtyness[2], dirtyness[3], dirtyness[4], dirtyness[5], dirtyness[6],
		        dirtyness[7], dirtyness[8], dirtyness[9], dirtyness[10], dirtyness[11], dirtyness[12], dirtyness[13]);

		    // RULE 1. pick up a good channel that no one used
		    for (ch=0; ch<pAd->ChannelListNum; ch++)
		    {
		        if (dirtyness[ch] == 0)		break;
		    }
		    if (ch < pAd->ChannelListNum)
		    {
		        DBGPRINT(RT_DEBUG_TRACE,"1.APAutoSelectChannel pick up ch#%d\n",pAd->ChannelList[ch].Channel);
		        return pAd->ChannelList[ch].Channel;
		    }

		    // RULE 2. if not available, pick up the channel with minimum RSSI
		    {
		        UCHAR min_rssi = 255, final_channel = 0;
		        
	            for (ch = 0; ch < pAd->ChannelListNum; ch++)
	            {
	                if (max_rssi[ch] < min_rssi)
	                {
	                    final_channel = ch;
	                    min_rssi = max_rssi[ch];
	                }
	            }
	            if (final_channel < pAd->ChannelListNum)
	            {
	                DBGPRINT(RT_DEBUG_TRACE,"2.APAutoSelectChannel pick up ch#%d\n",pAd->ChannelList[final_channel].Channel);
	                return pAd->ChannelList[final_channel].Channel;
	            }
		    }

		    // RULE 3. still not available, pick up the first channel
		    ch = FirstChannel(pAd);
		    DBGPRINT(RT_DEBUG_TRACE,"3.APAutoSelectChannel pick up ch#%d\n",ch);
    	}
		
    	DBGPRINT(RT_DEBUG_TRACE,"APAutoSelectChannel pick up ch#%d\n",ch);
    	return ch;
    }
    else
    {
	    for (ch=14; ch>=1; ch--)
	    {
	        AsicSwitchChannel(pAd, ch);
	        AsicLockChannel(pAd, ch);
	        pAd->Counters8023.GoodReceives = 0;
	        pAd->Counters8023.RxErrors = 0;
	        pAd->PortCfg.AutoChannel_MaxRssi = 0;
	        pAd->PortCfg.AutoChannel_Channel = ch;
	        max_rssi[ch]=0;
	        RTMPusecDelay(500000); // 0.5 sec at each channel
	        max_rssi[ch] = pAd->PortCfg.AutoChannel_MaxRssi;

	        RTMP_IO_READ32(pAd, STA_CSR1, &FalseCca);
	        FalseCca = FalseCca >> 16;
	        RTMP_IO_READ32(pAd, STA_CSR0, &FcsError);
	        FcsError &= 0x0000ffff;
	        
	        if (max_rssi[ch])
	        {
	            dirtyness[ch] += 10;
	            if (ch > 1) dirtyness[ch-1] += 1;
	            if (ch > 2) dirtyness[ch-2] += 1;
	            if (ch > 3) dirtyness[ch-3] += 1;
	            if (ch > 4) dirtyness[ch-4] += 1;
	            if (ch < 14) dirtyness[ch+1] += 1;
	            if (ch < 13) dirtyness[ch+2] += 1;
	            if (ch < 12) dirtyness[ch+3] += 1;
	            if (ch < 11) dirtyness[ch+4] += 1;
	        }
	        DBGPRINT(RT_DEBUG_TRACE,"Sleep at ch#%d to collect RX=%d, RSSI=%d, CRC error=%d, False CCA=%d\n", 
	            ch, pAd->Counters8023.GoodReceives, max_rssi[ch] - pAd->BbpRssiToDbmDelta, FcsError, FalseCca);
	    }
    
	    pAd->PortCfg.AutoChannel_Channel = 0;

	    DBGPRINT(RT_DEBUG_TRACE,"Dirtyness = %d.%d.%d.%d - %d.%d.%d.%d - %d.%d.%d.%d - %d.%d\n", 
	        dirtyness[1], dirtyness[2], dirtyness[3], dirtyness[4], dirtyness[5], dirtyness[6], dirtyness[7],
	        dirtyness[8], dirtyness[9], dirtyness[10], dirtyness[11], dirtyness[12], dirtyness[13], dirtyness[14]);

	    // RULE 1. pick up a good channel that no one used
	    for (ch = FirstChannel(pAd); ch !=0; ch = NextChannel(pAd, ch))
	    {
	        if (dirtyness[ch] == 0) break;
	    }
	    if (ch != 0)
	    {
	        DBGPRINT(RT_DEBUG_TRACE,"2.APAutoSelectChannel pick up ch#%d\n",ch);
	        return ch;
	    }

	    // RULE 2. if not available, then co-use a channel that's no interference (dirtyness=10)
	    // RULE 3. if not available, then co-use a channel that has minimum interference (dirtyness=11,12)
	    for (dirty = 10; dirty <= 12; dirty++)
	    {
	        UCHAR candidate[MAX_NUM_OF_CHANNELS+1], candidate_num;
	        UCHAR min_rssi = 255, final_channel = 0;
	        
	        candidate_num = 0;
	        NdisZeroMemory(candidate, MAX_NUM_OF_CHANNELS+1);
	        for (ch = FirstChannel(pAd); ch != 0; ch = NextChannel(pAd, ch))
	        {
	            if (dirtyness[ch] == dirty) 
	            { 
	                candidate[ch]=1; 
	                candidate_num++; 
	            }
	        }
	        // if there's more than 1 candidate, pick up the channel with minimum RSSI
	        if (candidate_num)
	        {
	            for (ch = 1; ch <= 14; ch ++)
	            {
	                if (candidate[ch] && (max_rssi[ch] < min_rssi))
	                {
	                    final_channel = ch;
	                    min_rssi = max_rssi[ch];
	                }
	            }
	            if (final_channel != 0)
	            {
	                DBGPRINT(RT_DEBUG_TRACE,"3.APAutoSelectChannel pick up ch#%d\n",final_channel);
	                return final_channel;
	            }
	        }
	    }

	    // RULE 4. still not available, pick up the first channel
	    ch = FirstChannel(pAd);
	    DBGPRINT(RT_DEBUG_TRACE,"4.APAutoSelectChannel pick up ch#%d\n",ch);
	    
	    return ch;
    }
}

/* 
    ==========================================================================
    Description:
        Send out a NULL frame to a specified STA at a higher TX rate. The 
        purpose is to ensure the designated client is okay to received at this
        rate.
    ==========================================================================
 */
VOID ApEnqueueNullFrame(
    IN PRTMP_ADAPTER pAd,
    IN PUCHAR        pAddr,
    IN UCHAR         TxRate,
    IN UCHAR         PID,
    IN UCHAR         Apidx,
    IN BOOLEAN       bQosNull,
    IN BOOLEAN       bEOSP,
    IN UCHAR         OldUP) 
{
	UCHAR			NullFrame[48];
    PHEADER_802_11 pNullFr;
    ULONG			Length;

    NdisZeroMemory(NullFrame, 48);
	Length = sizeof(HEADER_802_11);

    pNullFr = (PHEADER_802_11)NullFrame;

    // since TxRate may change, we have to change Duration each time
    if (pNullFr)
    {
#ifdef APCLI_SUPPORT    	
    	if ((PID & 0x3f) >= APCLI_PAIRWISE_KEY_OFFSET)
        {
    		// Send to Ap Client
            UCHAR ToWhichApCli = (PID & 0x3f) - APCLI_PAIRWISE_KEY_OFFSET;
            	
            NdisZeroMemory(pNullFr, sizeof(HEADER_802_11));
            pNullFr->FC.Type = BTYPE_DATA;
    		pNullFr->FC.SubType = SUBTYPE_NULL_FUNC;
    		pNullFr->FC.ToDs = 1;
    		COPY_MAC_ADDR(pNullFr->Addr1, pAd->ApCliTab.ApCliEntry[ToWhichApCli].ApCliBssid);
    		COPY_MAC_ADDR(pNullFr->Addr2, pAd->ApCliTab.ApCliEntry[ToWhichApCli].CurrentAddress);
    		COPY_MAC_ADDR(pNullFr->Addr3, pAd->ApCliTab.ApCliEntry[ToWhichApCli].ApCliBssid);
            pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, 14);
            ApSendFrame(pAd, pNullFr, Length, TxRate, PID);
        }
        else
#endif    	
    	if ((PID & 0x3f) >= WDS_PAIRWISE_KEY_OFFSET)
    	{	// Send to WDS
        	UCHAR ToWhichWds = (PID & 0x3f) - WDS_PAIRWISE_KEY_OFFSET;
        	
            NdisZeroMemory(pNullFr, LENGTH_802_11_WITH_ADDR4);
            pNullFr->FC.Type = BTYPE_DATA;
            pNullFr->FC.SubType = SUBTYPE_NULL_FUNC;
            pNullFr->FC.FrDs = 1;
            pNullFr->FC.ToDs = 1;
            COPY_MAC_ADDR(pNullFr->Addr1, pAd->WdsTab.WdsEntry[ToWhichWds].WdsAddr);
            COPY_MAC_ADDR(pNullFr->Addr2, pAd->PortCfg.MBSSID[MAIN_MBSSID].Bssid);
            COPY_MAC_ADDR(pNullFr->Addr3, pAd->WdsTab.WdsEntry[ToWhichWds].WdsAddr);
            COPY_MAC_ADDR(pNullFr->Addr3 + MAC_ADDR_LEN, pAd->PortCfg.MBSSID[MAIN_MBSSID].Bssid);
            pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, 14);
            ApSendFrame(pAd, pNullFr, LENGTH_802_11_WITH_ADDR4, TxRate, PID);
        }
    	else
    	{	// Send to BSS
    		MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_NULL_FUNC, 0, pAddr, pAd->PortCfg.MBSSID[Apidx].Bssid);
            pNullFr->FC.Type = BTYPE_DATA;
            pNullFr->FC.FrDs = 1;
            pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, 14);
            if (bQosNull)
			{
				pNullFr->FC.SubType = SUBTYPE_QOS_NULL;

				// copy QOS control bytes
				NullFrame[Length]	= ((bEOSP) ? (1 << 4) : 0) | OldUP;
				NullFrame[Length+1]	= 0;
				Length += 2;
			}
            ApSendFrame(pAd, pNullFr, Length, TxRate, PID);
    	}	
    }
}

VOID    ApSendFrame(
    IN  PRTMP_ADAPTER   pAd,
    IN  PVOID           pBuffer,
    IN  ULONG           Length,
    IN  UCHAR           TxRate,
    IN  UCHAR           PID)
{
    PUCHAR          pDest;
    PTXD_STRUC      pTxD;
    PRTMP_TX_RING   pTxRing = &pAd->TxRing[QID_AC_BE];
    ULONG			IrqFlags;
#ifdef BIG_ENDIAN
    PTXD_STRUC      pDestTxD;
    TXD_STRUC       TxD;
#endif

    if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)	||
    	RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)			||
    	RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
    {
        return;
    }

    // Make sure Tx ring resource won't be used by other threads
#ifndef THREAD_ISR
    RTMP_SEM_LOCK(&pAd->TxRingLock, IrqFlags);
#else
	RTMP_IRQ_LOCK(IrqFlags);
#endif

    // Get the Tx Ring descriptor & Dma Buffer address
    pDest = (PUCHAR) pTxRing->Cell[pTxRing->CurTxIndex].DmaBuf.AllocVa;
#ifndef BIG_ENDIAN
    pTxD  = (PTXD_STRUC) pTxRing->Cell[pTxRing->CurTxIndex].AllocVa;
#else
    pDestTxD  = (PTXD_STRUC) pTxRing->Cell[pTxRing->CurTxIndex].AllocVa;
    TxD = *pDestTxD;
    pTxD = &TxD;
    RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
#endif

    if ((pTxD->Owner == DESC_OWN_NIC) || (pTxD->bWaitingDmaDoneInt == 1))
    {
        // Descriptor owned by NIC. No descriptor avaliable
        // This should not happen since caller guaranteed.
        DBGPRINT_ERR("APSendNullFrame: TX RING full\n");
        pAd->RalinkCounters.TxRingErrCount++;
#ifndef THREAD_ISR      
        RTMP_SEM_UNLOCK(&pAd->TxRingLock, IrqFlags);
#else
		RTMP_IRQ_UNLOCK(IrqFlags);
#endif
        return;
    }
        
    DBGPRINT(RT_DEBUG_TRACE, "send NULL Frame @%d Mbps...\n", RateIdToMbps[TxRate]);
#ifdef BIG_ENDIAN
   RTMPFrameEndianChange(pAd, (PUCHAR)pBuffer, DIR_WRITE, FALSE);
#endif
    NdisMoveMemory(pDest, pBuffer, Length);
//  pTxRing->Cell[pTxRing->CurTxIndex].FrameType = BTYPE_DATA;

	pTxD->BufCount = 1;
	pTxD->BufLen0  = Length;

#ifdef BIG_ENDIAN
    RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
    *pDestTxD = TxD;
    pTxD = pDestTxD;
#endif

    RTMPWriteTxDescriptor(pAd, 
                          pTxD, 
                          CIPHER_NONE, 0, 0, 
                          TRUE, 
                          FALSE, 
                          FALSE, 
                          SHORT_RETRY, 
                          IFS_BACKOFF, 
                          TxRate, 
                          Length, 
                          QID_AC_BE,
                          PID,
                          NULL,
                          NULL,
                          FALSE,
                          FALSE,
                          FALSE,
                          FALSE);

    INC_RING_INDEX(pTxRing->CurTxIndex, TX_RING_SIZE);
    pAd->RalinkCounters.KickTxCount++;
#ifndef THREAD_ISR    
    RTMP_SEM_UNLOCK(&pAd->TxRingLock, IrqFlags);
#else
	RTMP_IRQ_UNLOCK(IrqFlags);
#endif

    RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, BIT8[QID_AC_BE]); // use AC_BE
}

VOID RTMPHandleNotify8021xDiscardSta(
    IN  PRTMP_ADAPTER	pAd,
    IN  MAC_TABLE_ENTRY *pEntry)
{
	INT				apidx = MAIN_MBSSID;
	UCHAR			SrcAddr[MAC_ADDR_LEN];
    UCHAR			DestAddr[MAC_ADDR_LEN];	
				
	apidx = pEntry->ApIdx;        
    COPY_MAC_ADDR(SrcAddr, pEntry->Addr);
    COPY_MAC_ADDR(DestAddr, pAd->PortCfg.MBSSID[apidx].Bssid);
    
    if((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pAd->PortCfg.MBSSID[apidx].IEEE8021X == TRUE))
	{
			UCHAR           	LLC_Len[2];
			UCHAR				Header802_3[14];
			UCHAR				RalinkDiscardIe[] = {0x01, 0xFE, 0x00, 0x06, 0x52, 0x61, 0x6c, 0x69, 0x6e, 0x6b};
			struct net_device	*net_dev = pAd->net_dev;
		                		
			net_dev = pAd->PortCfg.MBSSID[apidx].MSSIDDev;
			DBGPRINT(RT_DEBUG_TRACE, "Notify 8021.x daemon to remove this sta(%x %x %x %x %x %x)\n",SrcAddr[0],SrcAddr[1],SrcAddr[2],SrcAddr[3],SrcAddr[4],SrcAddr[5]);
		    
		    NdisMoveMemory(LLC_Len, EAPOL, 2);	
           	MAKE_802_3_HEADER(Header802_3, DestAddr, SrcAddr, ((PUCHAR) LLC_Len));
			
#ifdef RTL865X_SOC
		    REPORT_ETHERNET_FRAME_TO_LLC_RTL865X(pAd, Header802_3, RalinkDiscardIe, 10, net_dev);						
#else
		    REPORT_ETHERNET_FRAME_TO_LLC(pAd, Header802_3, RalinkDiscardIe, 10, net_dev);
#endif
	}	
}	    

⌨️ 快捷键说明

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